@contrast/contrast 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/audit/processAudit.js +10 -0
- package/dist/commands/scan/processScan.js +9 -0
- package/dist/commands/scan/sca/scaAnalysis.js +3 -0
- package/dist/common/HTTPClient.js +30 -2
- package/dist/common/fail.js +7 -3
- package/dist/common/versionChecker.js +11 -5
- package/dist/constants/constants.js +1 -1
- package/dist/constants/locales.js +2 -2
- package/dist/index.js +1 -1
- package/dist/lambda/lambda.js +7 -0
- package/dist/scaAnalysis/common/scaServicesUpload.js +52 -0
- package/dist/scaAnalysis/javascript/index.js +4 -0
- package/dist/scaAnalysis/javascript/scaServiceParser.js +109 -0
- package/dist/scaAnalysis/ruby/analysis.js +106 -9
- package/dist/scaAnalysis/ruby/index.js +6 -1
- package/dist/scan/scanResults.js +1 -1
- package/dist/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
- package/dist/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +14 -5
- package/package.json +1 -1
- package/src/commands/audit/processAudit.ts +8 -0
- package/src/commands/scan/processScan.js +14 -0
- package/src/commands/scan/sca/scaAnalysis.js +10 -0
- package/src/common/HTTPClient.js +44 -2
- package/src/common/fail.js +7 -3
- package/src/common/versionChecker.ts +16 -6
- package/src/constants/constants.js +1 -1
- package/src/constants/locales.js +2 -3
- package/src/index.ts +1 -2
- package/src/lambda/lambda.ts +12 -0
- package/src/scaAnalysis/common/scaServicesUpload.js +54 -0
- package/src/scaAnalysis/javascript/index.js +4 -0
- package/src/scaAnalysis/javascript/scaServiceParser.js +145 -0
- package/src/scaAnalysis/ruby/analysis.js +137 -9
- package/src/scaAnalysis/ruby/index.js +6 -1
- package/src/scan/scanResults.js +1 -1
- package/src/{audit/languageAnalysisEngine/util → utils}/capabilities.js +0 -0
- package/src/{audit/languageAnalysisEngine/util → utils}/generalAPI.js +16 -6
|
@@ -3,6 +3,7 @@ import { auditUsageGuide } from './help'
|
|
|
3
3
|
import { processSca } from '../scan/sca/scaAnalysis'
|
|
4
4
|
import { sendTelemetryConfigAsObject } from '../../telemetry/telemetry'
|
|
5
5
|
import { ContrastConf } from '../../utils/getConfig'
|
|
6
|
+
import chalk from 'chalk'
|
|
6
7
|
|
|
7
8
|
export type parameterInput = string[]
|
|
8
9
|
|
|
@@ -17,6 +18,7 @@ export const processAudit = async (
|
|
|
17
18
|
|
|
18
19
|
const config = await getAuditConfig(contrastConf, 'audit', argv)
|
|
19
20
|
await processSca(config)
|
|
21
|
+
postRunMessage()
|
|
20
22
|
await sendTelemetryConfigAsObject(
|
|
21
23
|
config,
|
|
22
24
|
'audit',
|
|
@@ -30,3 +32,9 @@ export const processAudit = async (
|
|
|
30
32
|
const printHelpMessage = () => {
|
|
31
33
|
console.log(auditUsageGuide)
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
const postRunMessage = () => {
|
|
37
|
+
console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
|
|
38
|
+
console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner")
|
|
39
|
+
console.log("'contrast lambda' to secure your AWS serverless functions\n")
|
|
40
|
+
}
|
|
@@ -6,10 +6,14 @@ const { formatScanOutput } = require('../../scan/formatScanOutput')
|
|
|
6
6
|
const { processSca } = require('./sca/scaAnalysis')
|
|
7
7
|
const common = require('../../common/fail')
|
|
8
8
|
const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry')
|
|
9
|
+
const chalk = require('chalk')
|
|
10
|
+
const generalAPI = require('../../utils/generalAPI')
|
|
9
11
|
|
|
10
12
|
const processScan = async (contrastConf, argv) => {
|
|
11
13
|
let config = await scanConfig.getScanConfig(contrastConf, 'scan', argv)
|
|
12
14
|
let output = undefined
|
|
15
|
+
config.mode = await generalAPI.getMode(config)
|
|
16
|
+
|
|
13
17
|
//try SCA analysis first
|
|
14
18
|
if (config.experimental) {
|
|
15
19
|
await processSca(config, argv)
|
|
@@ -35,6 +39,16 @@ const processScan = async (contrastConf, argv) => {
|
|
|
35
39
|
if (config.fail) {
|
|
36
40
|
common.processFail(config, output)
|
|
37
41
|
}
|
|
42
|
+
|
|
43
|
+
postRunMessage()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const postRunMessage = () => {
|
|
47
|
+
console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
|
|
48
|
+
console.log(
|
|
49
|
+
"'contrast audit' to find vulnerabilities in your open source dependencies"
|
|
50
|
+
)
|
|
51
|
+
console.log("'contrast lambda' to secure your AWS serverless functions\n")
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
module.exports = {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const autoDetection = require('../../../scan/autoDetection')
|
|
2
2
|
const javaAnalysis = require('../../../scaAnalysis/java')
|
|
3
3
|
const treeUpload = require('../../../scaAnalysis/common/treeUpload')
|
|
4
|
+
const scaUpload = require('../../../scaAnalysis/common/scaServicesUpload')
|
|
4
5
|
const auditController = require('../../audit/auditController')
|
|
5
6
|
const {
|
|
6
7
|
supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET }
|
|
@@ -27,7 +28,11 @@ const { dotNetAnalysis } = require('../../../scaAnalysis/dotnet')
|
|
|
27
28
|
const { auditUsageGuide } = require('../../audit/help')
|
|
28
29
|
const rootFile = require('../../../audit/languageAnalysisEngine/getProjectRootFilenames')
|
|
29
30
|
const path = require('path')
|
|
31
|
+
const generalAPI = require('../../../utils/generalAPI')
|
|
32
|
+
|
|
30
33
|
const processSca = async config => {
|
|
34
|
+
config.mode = await generalAPI.getMode(config)
|
|
35
|
+
|
|
31
36
|
const startTime = performance.now()
|
|
32
37
|
let filesFound
|
|
33
38
|
|
|
@@ -99,6 +104,10 @@ const processSca = async config => {
|
|
|
99
104
|
config.applicationId = await auditController.dealWithNoAppId(config)
|
|
100
105
|
}
|
|
101
106
|
|
|
107
|
+
// if (config.experimental) {
|
|
108
|
+
// await scaUpload.scaTreeUpload(messageToSend, config)
|
|
109
|
+
// } else
|
|
110
|
+
// {
|
|
102
111
|
console.log('') //empty log for space before spinner
|
|
103
112
|
//send message to TS
|
|
104
113
|
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'))
|
|
@@ -126,6 +135,7 @@ const processSca = async config => {
|
|
|
126
135
|
console.log(
|
|
127
136
|
`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`
|
|
128
137
|
)
|
|
138
|
+
// }
|
|
129
139
|
} else {
|
|
130
140
|
if (filesFound.length === 0) {
|
|
131
141
|
console.log(i18n.__('languageAnalysisNoLanguage'))
|
package/src/common/HTTPClient.js
CHANGED
|
@@ -171,9 +171,9 @@ HTTPClient.prototype.getScanProjectById = function getScanProjectById(config) {
|
|
|
171
171
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
HTTPClient.prototype.getGlobalProperties = function getGlobalProperties() {
|
|
174
|
+
HTTPClient.prototype.getGlobalProperties = function getGlobalProperties(host) {
|
|
175
175
|
const options = _.cloneDeep(this.requestOptions)
|
|
176
|
-
let url = createGlobalPropertiesUrl(
|
|
176
|
+
let url = createGlobalPropertiesUrl(host)
|
|
177
177
|
options.url = url
|
|
178
178
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
179
179
|
}
|
|
@@ -216,6 +216,36 @@ HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
|
|
|
216
216
|
return requestUtils.sendRequest({ method: 'post', options })
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
HTTPClient.prototype.scaServiceIngest = function scaServiceIngest(
|
|
220
|
+
requestBody,
|
|
221
|
+
config
|
|
222
|
+
) {
|
|
223
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
224
|
+
let url = createScaServiceIngestURL(config)
|
|
225
|
+
options.url = url
|
|
226
|
+
options.body = requestBody
|
|
227
|
+
return requestUtils.sendRequest({ method: 'post', options })
|
|
228
|
+
}
|
|
229
|
+
HTTPClient.prototype.scaServiceReport = function scaServiceReport(
|
|
230
|
+
config,
|
|
231
|
+
reportId
|
|
232
|
+
) {
|
|
233
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
234
|
+
let url = createScaServiceReportURL(config, reportId)
|
|
235
|
+
options.url = url
|
|
236
|
+
return requestUtils.sendRequest({ method: 'get', options })
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
HTTPClient.prototype.scaServiceReportStatus = function scaServiceReport(
|
|
240
|
+
config,
|
|
241
|
+
reportId
|
|
242
|
+
) {
|
|
243
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
244
|
+
let url = createScaServiceReportStatusURL(config, reportId)
|
|
245
|
+
options.url = url
|
|
246
|
+
return requestUtils.sendRequest({ method: 'get', options })
|
|
247
|
+
}
|
|
248
|
+
|
|
219
249
|
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
220
250
|
const options = _.cloneDeep(this.requestOptions)
|
|
221
251
|
if (config.ignoreDev) {
|
|
@@ -416,6 +446,18 @@ function createSnapshotURL(config) {
|
|
|
416
446
|
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots`
|
|
417
447
|
}
|
|
418
448
|
|
|
449
|
+
function createScaServiceReportURL(config, reportId) {
|
|
450
|
+
return ``
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function createScaServiceReportStatusURL(config, reportId) {
|
|
454
|
+
return ``
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function createScaServiceIngestURL(config) {
|
|
458
|
+
return ``
|
|
459
|
+
}
|
|
460
|
+
|
|
419
461
|
const createAppCreateURL = config => {
|
|
420
462
|
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/create`
|
|
421
463
|
}
|
package/src/common/fail.js
CHANGED
|
@@ -25,11 +25,15 @@ const isSeverityViolation = (severity, reportResults) => {
|
|
|
25
25
|
count += reportResults.high + reportResults.critical
|
|
26
26
|
break
|
|
27
27
|
case 'medium':
|
|
28
|
-
count +=
|
|
28
|
+
count +=
|
|
29
|
+
reportResults.medium + reportResults.high + reportResults.critical
|
|
29
30
|
break
|
|
30
31
|
case 'low':
|
|
31
32
|
count +=
|
|
32
|
-
reportResults.high +
|
|
33
|
+
reportResults.high +
|
|
34
|
+
reportResults.critical +
|
|
35
|
+
reportResults.medium +
|
|
36
|
+
reportResults.low
|
|
33
37
|
break
|
|
34
38
|
case 'note':
|
|
35
39
|
if (reportResults.note == reportResults.total) {
|
|
@@ -51,7 +55,7 @@ const failPipeline = (message = '') => {
|
|
|
51
55
|
' *********************************\n' +
|
|
52
56
|
i18n.__(message)
|
|
53
57
|
)
|
|
54
|
-
process.exit(
|
|
58
|
+
process.exit(2)
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
const parseSeverity = severity => {
|
|
@@ -6,7 +6,7 @@ import commonApi from '../utils/commonApi'
|
|
|
6
6
|
import { constants } from 'http2'
|
|
7
7
|
import { ContrastConf } from '../utils/getConfig'
|
|
8
8
|
|
|
9
|
-
const getLatestVersion = async (config:
|
|
9
|
+
export const getLatestVersion = async (config: ContrastConf) => {
|
|
10
10
|
const client = commonApi.getHttpClient(config)
|
|
11
11
|
try {
|
|
12
12
|
const res = await client.getLatestVersion()
|
|
@@ -14,18 +14,28 @@ const getLatestVersion = async (config: any) => {
|
|
|
14
14
|
return res.body
|
|
15
15
|
}
|
|
16
16
|
} catch (e) {
|
|
17
|
-
return
|
|
17
|
+
return undefined
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export async function findLatestCLIVersion(config: ContrastConf) {
|
|
22
22
|
const isCI = process.env.CONTRAST_CODESEC_CI
|
|
23
|
-
? JSON.parse(process.env.CONTRAST_CODESEC_CI)
|
|
23
|
+
? JSON.parse(process.env.CONTRAST_CODESEC_CI.toLowerCase())
|
|
24
24
|
: false
|
|
25
|
+
|
|
25
26
|
if (!isCI) {
|
|
26
|
-
let latestCLIVersion
|
|
27
|
-
|
|
28
|
-
latestCLIVersion
|
|
27
|
+
let latestCLIVersion = await getLatestVersion(config)
|
|
28
|
+
|
|
29
|
+
if (latestCLIVersion === undefined) {
|
|
30
|
+
config.set('numOfRuns', 0)
|
|
31
|
+
console.log(
|
|
32
|
+
'Failed to retrieve latest version info. Continuing execution.'
|
|
33
|
+
)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//strip key and remove new lines
|
|
38
|
+
latestCLIVersion = latestCLIVersion.substring(8).replace('\n', '')
|
|
29
39
|
|
|
30
40
|
if (semver.lt(APP_VERSION, latestCLIVersion)) {
|
|
31
41
|
const updateAvailableMessage = `Update available ${chalk.yellow(
|
package/src/constants/locales.js
CHANGED
|
@@ -26,8 +26,7 @@ const en_locales = () => {
|
|
|
26
26
|
unauthenticatedErrorMessage:
|
|
27
27
|
'Please check the following keys are correct:\n--organization-id, --api-key or --authorization',
|
|
28
28
|
badRequestErrorHeader: '400 error - Bad Request',
|
|
29
|
-
badRequestErrorMessage:
|
|
30
|
-
'Please check the following key is correct: \n--application-id',
|
|
29
|
+
badRequestErrorMessage: 'Please check your parameters and try again',
|
|
31
30
|
badRequestCatalogueErrorMessage:
|
|
32
31
|
'The application name already exists, please use a unique name',
|
|
33
32
|
forbiddenRequestErrorHeader: '403 error - Forbidden',
|
|
@@ -318,7 +317,7 @@ const en_locales = () => {
|
|
|
318
317
|
scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
|
|
319
318
|
authSuccessMessage: 'Authentication successful',
|
|
320
319
|
runAuthSuccessMessage:
|
|
321
|
-
"Now you can use CodeSec by Contrast \nRun: \n'contrast scan'
|
|
320
|
+
"Now you can use CodeSec by Contrast \nRun: \n'contrast scan' to run CodeSec’s industry leading SAST scanner \n'contrast audit' to find vulnerabilities in your open source dependencies \n'contrast lambda' to secure your AWS serverless functions\nor 'contrast help' to learn more about the capabilities.",
|
|
322
321
|
authWaitingMessage: 'Waiting for auth...',
|
|
323
322
|
authTimedOutMessage: 'Auth Timed out, try again',
|
|
324
323
|
zipErrorScan:
|
package/src/index.ts
CHANGED
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
} from './common/versionChecker'
|
|
16
16
|
import { findCommandOnError } from './common/errorHandling'
|
|
17
17
|
import { sendTelemetryConfigAsConfObj } from './telemetry/telemetry'
|
|
18
|
-
|
|
19
18
|
const {
|
|
20
19
|
commandLineDefinitions: { mainUsageGuide, mainDefinition }
|
|
21
20
|
} = constants
|
|
@@ -58,7 +57,7 @@ const start = async () => {
|
|
|
58
57
|
config.set('numOfRuns', config.get('numOfRuns') + 1)
|
|
59
58
|
|
|
60
59
|
// @ts-ignore
|
|
61
|
-
if (config.get('numOfRuns') >=
|
|
60
|
+
if (config.get('numOfRuns') >= 10) {
|
|
62
61
|
await findLatestCLIVersion(config)
|
|
63
62
|
config.set('numOfRuns', 0)
|
|
64
63
|
}
|
package/src/lambda/lambda.ts
CHANGED
|
@@ -17,6 +17,7 @@ import ora from '../utils/oraWrapper'
|
|
|
17
17
|
import { postAnalytics } from './analytics'
|
|
18
18
|
import { LambdaOptions, AnalyticsOption, StatusType, EventType } from './types'
|
|
19
19
|
import { APP_VERSION } from '../constants/constants'
|
|
20
|
+
import chalk from 'chalk'
|
|
20
21
|
|
|
21
22
|
type ApiParams = {
|
|
22
23
|
organizationId: string
|
|
@@ -114,6 +115,9 @@ const processLambda = async (argv: string[]) => {
|
|
|
114
115
|
await postAnalytics(endCommandAnalytics).catch((error: Error) => {
|
|
115
116
|
/* ignore */
|
|
116
117
|
})
|
|
118
|
+
|
|
119
|
+
postRunMessage()
|
|
120
|
+
|
|
117
121
|
if (errorMsg) {
|
|
118
122
|
process.exit(1)
|
|
119
123
|
}
|
|
@@ -221,4 +225,12 @@ const handleLambdaHelp = () => {
|
|
|
221
225
|
process.exit(0)
|
|
222
226
|
}
|
|
223
227
|
|
|
228
|
+
const postRunMessage = () => {
|
|
229
|
+
console.log('\n' + chalk.underline.bold('Other Codesec Features:'))
|
|
230
|
+
console.log("'contrast scan' to run CodeSec’s industry leading SAST scanner")
|
|
231
|
+
console.log(
|
|
232
|
+
"'contrast audit' to find vulnerabilities in your open source dependencies\n"
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
|
|
224
236
|
export { processLambda, LambdaOptions, ApiParams, getAvailableFunctions }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const commonApi = require('../../utils/commonApi')
|
|
2
|
+
const { APP_VERSION } = require('../../constants/constants')
|
|
3
|
+
const requestUtils = require('../../utils/requestUtils')
|
|
4
|
+
|
|
5
|
+
const scaTreeUpload = async (analysis, config) => {
|
|
6
|
+
const requestBody = {
|
|
7
|
+
applicationId: config.applicationId,
|
|
8
|
+
dependencyTree: analysis,
|
|
9
|
+
organizationId: config.organizationId,
|
|
10
|
+
language: 'NODE',
|
|
11
|
+
tool: {
|
|
12
|
+
name: 'Contrast Codesec',
|
|
13
|
+
version: APP_VERSION
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const client = commonApi.getHttpClient(config)
|
|
18
|
+
const reportID = await client
|
|
19
|
+
.scaServiceIngest(requestBody, config)
|
|
20
|
+
.then(res => {
|
|
21
|
+
if (res.statusCode === 201) {
|
|
22
|
+
return res.body.libraryIngestJobId
|
|
23
|
+
} else {
|
|
24
|
+
throw new Error(res.statusCode + ` error ingesting dependencies`)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
.catch(err => {
|
|
28
|
+
throw err
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
let keepChecking = true
|
|
32
|
+
while (keepChecking) {
|
|
33
|
+
keepChecking = await client
|
|
34
|
+
.scaServiceReportStatus(config, reportID)
|
|
35
|
+
.then(res => {
|
|
36
|
+
console.log(res.body)
|
|
37
|
+
if (res.body.status == 'COMPLETED') {
|
|
38
|
+
client.scaServiceReport(config, reportID).then(res => {
|
|
39
|
+
console.log(res.statusCode)
|
|
40
|
+
console.log(res.body)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return (keepChecking = false)
|
|
44
|
+
} else {
|
|
45
|
+
return (keepChecking = true)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
await requestUtils.sleep(5000)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
scaTreeUpload
|
|
54
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const analysis = require('./analysis')
|
|
2
2
|
const i18n = require('i18n')
|
|
3
3
|
const formatMessage = require('../common/formatMessage')
|
|
4
|
+
const scaServiceParser = require('./scaServiceParser')
|
|
4
5
|
|
|
5
6
|
const jsAnalysis = async (config, languageFiles) => {
|
|
6
7
|
checkForCorrectFiles(languageFiles)
|
|
@@ -13,6 +14,9 @@ const jsAnalysis = async (config, languageFiles) => {
|
|
|
13
14
|
const buildNodeTree = async (config, files) => {
|
|
14
15
|
let analysis = await readFiles(config, files)
|
|
15
16
|
const rawNode = await parseFiles(config, files, analysis)
|
|
17
|
+
if (config.experimental) {
|
|
18
|
+
return scaServiceParser.parseJS(rawNode)
|
|
19
|
+
}
|
|
16
20
|
return formatMessage.createJavaScriptTSMessage(rawNode)
|
|
17
21
|
}
|
|
18
22
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
const parseJS = rawNode => {
|
|
2
|
+
let dependencyTree = {}
|
|
3
|
+
let combinedPackageJSONDep = {
|
|
4
|
+
...rawNode.packageJSON?.dependencies,
|
|
5
|
+
...rawNode.packageJSON?.devDependencies
|
|
6
|
+
}
|
|
7
|
+
let analyseLock = chooseLockFile(rawNode)
|
|
8
|
+
|
|
9
|
+
if (analyseLock.type === 'yarn') {
|
|
10
|
+
dependencyTree = yarnCreateDepTree(
|
|
11
|
+
dependencyTree,
|
|
12
|
+
combinedPackageJSONDep,
|
|
13
|
+
analyseLock.lockFile,
|
|
14
|
+
rawNode
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (analyseLock.type === 'npm') {
|
|
19
|
+
dependencyTree = npmCreateDepTree(
|
|
20
|
+
dependencyTree,
|
|
21
|
+
combinedPackageJSONDep,
|
|
22
|
+
analyseLock.lockFile,
|
|
23
|
+
rawNode
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return dependencyTree
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const npmCreateDepTree = (
|
|
31
|
+
dependencyTree,
|
|
32
|
+
combinedPackageJSONDep,
|
|
33
|
+
packageLock,
|
|
34
|
+
rawNode
|
|
35
|
+
) => {
|
|
36
|
+
for (const [key, value] of Object.entries(packageLock)) {
|
|
37
|
+
dependencyTree[key] = {
|
|
38
|
+
name: key,
|
|
39
|
+
version: getResolvedVersion(key, packageLock),
|
|
40
|
+
group: null,
|
|
41
|
+
isProduction: checkIfInPackageJSON(rawNode.packageJSON.dependencies, key),
|
|
42
|
+
directDependency: checkIfInPackageJSON(combinedPackageJSONDep, key),
|
|
43
|
+
dependencies: createNPMChildDependencies(packageLock, key)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return dependencyTree
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const yarnCreateDepTree = (
|
|
50
|
+
dependencyTree,
|
|
51
|
+
combinedPackageJSONDep,
|
|
52
|
+
packageLock,
|
|
53
|
+
rawNode
|
|
54
|
+
) => {
|
|
55
|
+
for (const [key, value] of Object.entries(packageLock)) {
|
|
56
|
+
let gav = getNameFromGAV(key)
|
|
57
|
+
let nag = getDepNameWithoutVersion(key)
|
|
58
|
+
dependencyTree[key] = {
|
|
59
|
+
name: gav,
|
|
60
|
+
version: getResolvedVersion(key, packageLock),
|
|
61
|
+
group: null,
|
|
62
|
+
isProduction: checkIfInPackageJSON(rawNode.packageJSON.dependencies, nag),
|
|
63
|
+
directDependency: checkIfInPackageJSON(combinedPackageJSONDep, nag),
|
|
64
|
+
dependencies: createChildDependencies(packageLock, key)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return dependencyTree
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const chooseLockFile = rawNode => {
|
|
71
|
+
if (rawNode?.yarn?.yarnLockFile !== undefined) {
|
|
72
|
+
return { lockFile: rawNode?.yarn?.yarnLockFile?.object, type: 'yarn' }
|
|
73
|
+
} else if (rawNode.npmLockFile !== undefined) {
|
|
74
|
+
return { lockFile: rawNode?.npmLockFile?.dependencies, type: 'npm' }
|
|
75
|
+
} else {
|
|
76
|
+
return undefined
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const createKeyName = (dep, version) => {
|
|
81
|
+
return dep + '@' + version
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const checkIfInPackageJSON = (list, dep) => {
|
|
85
|
+
return Object.keys(list).includes(dep)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const createChildDependencies = (lockFileDep, currentDep) => {
|
|
89
|
+
let depArray = []
|
|
90
|
+
if (lockFileDep[currentDep]?.dependencies) {
|
|
91
|
+
for (const [key, value] of Object.entries(
|
|
92
|
+
lockFileDep[currentDep]?.dependencies
|
|
93
|
+
)) {
|
|
94
|
+
depArray.push(createKeyName(key, value))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return depArray
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const createNPMChildDependencies = (lockFileDep, currentDep) => {
|
|
101
|
+
let depArray = []
|
|
102
|
+
if (lockFileDep[currentDep]?.requires) {
|
|
103
|
+
for (const [key, value] of Object.entries(
|
|
104
|
+
lockFileDep[currentDep]?.requires
|
|
105
|
+
)) {
|
|
106
|
+
depArray.push(key)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return depArray
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const getDepNameWithoutVersion = depKey => {
|
|
113
|
+
let dependency = depKey.split('@')
|
|
114
|
+
if (dependency.length - 1 > 1) {
|
|
115
|
+
return '@' + dependency[1]
|
|
116
|
+
}
|
|
117
|
+
return dependency[0]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const getNameFromGAV = depKey => {
|
|
121
|
+
let dependency = depKey.split('/')
|
|
122
|
+
if (dependency.length == 2) {
|
|
123
|
+
dependency = getDepNameWithoutVersion(dependency[1])
|
|
124
|
+
return dependency
|
|
125
|
+
}
|
|
126
|
+
if (dependency.length == 1) {
|
|
127
|
+
dependency = getDepNameWithoutVersion(depKey)
|
|
128
|
+
return dependency
|
|
129
|
+
}
|
|
130
|
+
//what should we do if there's no version? The service will fall over but do we want to throw error for only one wrong version?
|
|
131
|
+
return depKey
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const getResolvedVersion = (depKey, packageLock) => {
|
|
135
|
+
return packageLock[depKey]?.version
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
parseJS,
|
|
140
|
+
checkIfInPackageJSON,
|
|
141
|
+
getNameFromGAV,
|
|
142
|
+
getResolvedVersion,
|
|
143
|
+
chooseLockFile,
|
|
144
|
+
createNPMChildDependencies
|
|
145
|
+
}
|