@contrast/contrast 1.0.0 → 1.0.3
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/.prettierignore +3 -0
- package/README.md +115 -78
- package/dist/audit/AnalysisEngine.js +37 -0
- package/dist/audit/catalogueApplication/catalogueApplication.js +36 -0
- package/dist/audit/dotnetAnalysisEngine/index.js +25 -0
- package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +35 -0
- package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +15 -0
- package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +18 -0
- package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +14 -0
- package/dist/audit/dotnetAnalysisEngine/sanitizer.js +9 -0
- package/dist/audit/goAnalysisEngine/index.js +17 -0
- package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +164 -0
- package/dist/audit/goAnalysisEngine/readProjectFileContents.js +21 -0
- package/dist/audit/goAnalysisEngine/sanitizer.js +5 -0
- package/dist/audit/javaAnalysisEngine/index.js +34 -0
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +153 -0
- package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +353 -0
- package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +98 -0
- package/dist/audit/javaAnalysisEngine/sanitizer.js +5 -0
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +24 -0
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +24 -0
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +35 -0
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +23 -0
- package/dist/audit/languageAnalysisEngine/commonApi.js +18 -0
- package/dist/audit/languageAnalysisEngine/constants.js +20 -0
- package/dist/audit/languageAnalysisEngine/filterProjectPath.js +20 -0
- package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +25 -0
- package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +39 -0
- package/dist/audit/languageAnalysisEngine/index.js +39 -0
- package/dist/audit/languageAnalysisEngine/langugageAnalysisFactory.js +95 -0
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +121 -0
- package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +17 -0
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +257 -0
- package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +81 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +133 -0
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +41 -0
- package/dist/audit/languageAnalysisEngine/util/capabilities.js +11 -0
- package/dist/audit/languageAnalysisEngine/util/generalAPI.js +39 -0
- package/dist/audit/languageAnalysisEngine/util/requestUtils.js +14 -0
- package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +40 -0
- package/dist/audit/nodeAnalysisEngine/index.js +31 -0
- package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +18 -0
- package/dist/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +51 -0
- package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +18 -0
- package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +17 -0
- package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +14 -0
- package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +24 -0
- package/dist/audit/nodeAnalysisEngine/sanitizer.js +9 -0
- package/dist/audit/phpAnalysisEngine/index.js +23 -0
- package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +52 -0
- package/dist/audit/phpAnalysisEngine/readLockFileContents.js +13 -0
- package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +16 -0
- package/dist/audit/phpAnalysisEngine/sanitizer.js +5 -0
- package/dist/audit/pythonAnalysisEngine/index.js +25 -0
- package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +17 -0
- package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +21 -0
- package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +13 -0
- package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +14 -0
- package/dist/audit/pythonAnalysisEngine/sanitizer.js +7 -0
- package/dist/audit/rubyAnalysisEngine/index.js +25 -0
- package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +176 -0
- package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +22 -0
- package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +14 -0
- package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +14 -0
- package/dist/audit/rubyAnalysisEngine/sanitizer.js +6 -0
- package/dist/commands/audit/auditConfig.js +25 -0
- package/dist/commands/audit/auditController.js +31 -0
- package/dist/commands/audit/help.js +52 -0
- package/dist/commands/audit/processAudit.js +18 -0
- package/dist/commands/audit/saveFile.js +11 -0
- package/dist/commands/auth/auth.js +20 -2
- package/dist/commands/config/config.js +19 -8
- package/dist/commands/scan/processScan.js +9 -13
- package/dist/common/HTTPClient.js +112 -13
- package/dist/common/errorHandling.js +65 -1
- package/dist/common/versionChecker.js +30 -0
- package/dist/constants/constants.js +4 -2
- package/dist/constants/lambda.js +32 -4
- package/dist/constants/locales.js +60 -21
- package/dist/constants.js +181 -21
- package/dist/index.js +50 -23
- package/dist/lambda/aws.js +14 -11
- package/dist/lambda/help.js +4 -0
- package/dist/lambda/lambda.js +50 -27
- package/dist/lambda/lambdaUtils.js +72 -0
- package/dist/lambda/logUtils.js +11 -1
- package/dist/lambda/scanDetailCompletion.js +4 -4
- package/dist/lambda/scanRequest.js +11 -5
- package/dist/lambda/utils.js +110 -53
- package/dist/sbom/generateSbom.js +20 -0
- package/dist/scan/autoDetection.js +0 -32
- package/dist/scan/fileUtils.js +1 -1
- package/dist/scan/help.js +14 -40
- package/dist/scan/populateProjectIdAndProjectName.js +5 -0
- package/dist/scan/saveResults.js +14 -0
- package/dist/scan/scan.js +105 -40
- package/dist/scan/scanConfig.js +39 -0
- package/dist/scan/scanController.js +19 -16
- package/dist/scan/scanResults.js +24 -16
- package/dist/utils/commonApi.js +3 -3
- package/dist/utils/paramsUtil/commandlineParams.js +1 -20
- package/dist/utils/paramsUtil/paramHandler.js +3 -6
- package/dist/utils/parsedCLIOptions.js +14 -8
- package/dist/utils/requestUtils.js +1 -1
- package/dist/utils/saveFile.js +19 -0
- package/package.json +26 -21
- package/src/audit/AnalysisEngine.js +103 -0
- package/src/audit/catalogueApplication/catalogueApplication.js +42 -0
- package/src/audit/dotnetAnalysisEngine/index.js +26 -0
- package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +47 -0
- package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +29 -0
- package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +30 -0
- package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +26 -0
- package/src/audit/dotnetAnalysisEngine/sanitizer.js +11 -0
- package/src/audit/goAnalysisEngine/index.js +18 -0
- package/src/audit/goAnalysisEngine/parseProjectFileContents.js +209 -0
- package/src/audit/goAnalysisEngine/readProjectFileContents.js +31 -0
- package/src/audit/goAnalysisEngine/sanitizer.js +7 -0
- package/src/audit/javaAnalysisEngine/index.js +41 -0
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +222 -0
- package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +420 -0
- package/src/audit/javaAnalysisEngine/readProjectFileContents.js +141 -0
- package/src/audit/javaAnalysisEngine/sanitizer.js +6 -0
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +35 -0
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +41 -0
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +54 -0
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +32 -0
- package/src/audit/languageAnalysisEngine/commonApi.js +20 -0
- package/src/audit/languageAnalysisEngine/constants.js +23 -0
- package/src/audit/languageAnalysisEngine/filterProjectPath.js +21 -0
- package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +41 -0
- package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +72 -0
- package/src/audit/languageAnalysisEngine/index.js +45 -0
- package/src/audit/languageAnalysisEngine/langugageAnalysisFactory.js +126 -0
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +177 -0
- package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +27 -0
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +303 -0
- package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +124 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.js +190 -0
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +51 -0
- package/src/audit/languageAnalysisEngine/util/capabilities.js +12 -0
- package/src/audit/languageAnalysisEngine/util/generalAPI.js +43 -0
- package/src/audit/languageAnalysisEngine/util/requestUtils.js +17 -0
- package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +49 -0
- package/src/audit/nodeAnalysisEngine/index.js +35 -0
- package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +20 -0
- package/src/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +63 -0
- package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +26 -0
- package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +23 -0
- package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +27 -0
- package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +36 -0
- package/src/audit/nodeAnalysisEngine/sanitizer.js +11 -0
- package/src/audit/phpAnalysisEngine/index.js +27 -0
- package/src/audit/phpAnalysisEngine/parseLockFileContents.js +60 -0
- package/src/audit/phpAnalysisEngine/readLockFileContents.js +14 -0
- package/src/audit/phpAnalysisEngine/readProjectFileContents.js +25 -0
- package/src/audit/phpAnalysisEngine/sanitizer.js +4 -0
- package/src/audit/pythonAnalysisEngine/index.js +55 -0
- package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +23 -0
- package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +33 -0
- package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +16 -0
- package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +22 -0
- package/src/audit/pythonAnalysisEngine/sanitizer.js +9 -0
- package/src/audit/rubyAnalysisEngine/index.js +30 -0
- package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +215 -0
- package/src/audit/rubyAnalysisEngine/parsedGemfile.js +39 -0
- package/src/audit/rubyAnalysisEngine/readGemfileContents.js +18 -0
- package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +17 -0
- package/src/audit/rubyAnalysisEngine/sanitizer.js +8 -0
- package/src/commands/audit/auditConfig.ts +30 -0
- package/src/commands/audit/auditController.ts +31 -0
- package/src/commands/audit/help.ts +48 -0
- package/src/commands/audit/processAudit.ts +18 -0
- package/src/commands/audit/saveFile.ts +6 -0
- package/src/commands/auth/auth.js +26 -2
- package/src/commands/config/config.js +22 -8
- package/src/commands/scan/processScan.js +9 -13
- package/src/common/HTTPClient.js +149 -14
- package/src/common/errorHandling.ts +85 -2
- package/src/common/versionChecker.ts +39 -0
- package/src/constants/constants.js +5 -4
- package/src/constants/lambda.js +45 -4
- package/src/constants/locales.js +76 -26
- package/src/constants.js +204 -23
- package/src/index.ts +67 -27
- package/src/lambda/aws.ts +13 -12
- package/src/lambda/help.ts +4 -0
- package/src/lambda/lambda.ts +53 -34
- package/src/lambda/lambdaUtils.ts +111 -0
- package/src/lambda/logUtils.ts +19 -1
- package/src/lambda/scanDetailCompletion.ts +4 -4
- package/src/lambda/scanRequest.ts +13 -11
- package/src/lambda/utils.ts +149 -81
- package/src/sbom/generateSbom.ts +17 -0
- package/src/scan/autoDetection.js +0 -29
- package/src/scan/fileUtils.js +1 -1
- package/src/scan/help.js +14 -45
- package/src/scan/populateProjectIdAndProjectName.js +5 -0
- package/src/scan/saveResults.js +14 -0
- package/src/scan/scan.js +127 -58
- package/src/scan/scanConfig.js +54 -0
- package/src/scan/scanController.js +22 -15
- package/src/scan/scanResults.js +32 -19
- package/src/utils/commonApi.js +2 -3
- package/src/utils/getConfig.ts +2 -0
- package/src/utils/paramsUtil/commandlineParams.js +1 -26
- package/src/utils/paramsUtil/paramHandler.js +3 -7
- package/src/utils/parsedCLIOptions.js +11 -9
- package/src/utils/requestUtils.js +1 -1
- package/src/utils/saveFile.js +19 -0
- package/dist/lambda/scanDetail.js +0 -30
- package/dist/scan/fileFinder.js +0 -15
- package/dist/utils/paramsUtil/yamlParams.js +0 -6
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const i18n = require('i18n');
|
|
3
|
+
const { getHttpClient } = require('../../../utils/commonApi');
|
|
4
|
+
function displaySuccessMessageReport() {
|
|
5
|
+
console.log('\n' + i18n.__('reportSuccessMessage'));
|
|
6
|
+
}
|
|
7
|
+
function getAllDependenciesArray(packageJson) {
|
|
8
|
+
const { dependencies, optionalDependencies, devDependencies, peerDependencies } = packageJson;
|
|
9
|
+
const allDep = {
|
|
10
|
+
...dependencies,
|
|
11
|
+
...devDependencies,
|
|
12
|
+
...optionalDependencies,
|
|
13
|
+
...peerDependencies
|
|
14
|
+
};
|
|
15
|
+
return Object.entries(allDep);
|
|
16
|
+
}
|
|
17
|
+
function checkIfDepIsScoped(arrDep) {
|
|
18
|
+
let count = 0;
|
|
19
|
+
arrDep.forEach(([key, value]) => {
|
|
20
|
+
if (!key.startsWith('@')) {
|
|
21
|
+
console.log(` WARNING not scoped: ${key}:${value}`);
|
|
22
|
+
count++;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return count;
|
|
26
|
+
}
|
|
27
|
+
const dependencyRiskReport = async (packageJson, config) => {
|
|
28
|
+
const arrDep = getAllDependenciesArray(packageJson);
|
|
29
|
+
const unRegisteredDeps = await checkIfDepIsRegisteredOnNPM(arrDep, config);
|
|
30
|
+
let scopedCount = checkIfDepIsScoped(unRegisteredDeps);
|
|
31
|
+
return {
|
|
32
|
+
scopedCount: scopedCount,
|
|
33
|
+
unRegisteredCount: unRegisteredDeps.length
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
const checkIfDepIsRegisteredOnNPM = async (arrDep, config) => {
|
|
37
|
+
let promises = [];
|
|
38
|
+
let unRegisteredDeps = [];
|
|
39
|
+
const client = getHttpClient(config);
|
|
40
|
+
for (const [index, element] of arrDep) {
|
|
41
|
+
const query = `query artifactByGAV($name: String!, $language: String!, $groupName: String, $version: String!, $nameCheck: Boolean) {
|
|
42
|
+
artifact: exactVersion(name: $name, language: $language, groupName: $groupName, version: $version, nameCheck: $nameCheck) {
|
|
43
|
+
version
|
|
44
|
+
cves {
|
|
45
|
+
baseScore
|
|
46
|
+
}}}`;
|
|
47
|
+
const data = {
|
|
48
|
+
query: query,
|
|
49
|
+
variables: {
|
|
50
|
+
name: index,
|
|
51
|
+
version: element,
|
|
52
|
+
language: 'node',
|
|
53
|
+
nameCheck: true
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
promises.push(client.checkLibrary(data));
|
|
57
|
+
}
|
|
58
|
+
await Promise.all(promises).then(response => {
|
|
59
|
+
response.forEach(res => {
|
|
60
|
+
const libName = JSON.parse(res.request.body);
|
|
61
|
+
if (res.statusCode === 200) {
|
|
62
|
+
if (res.body.data.artifact == null) {
|
|
63
|
+
unRegisteredDeps.push([
|
|
64
|
+
libName.variables.name,
|
|
65
|
+
libName.variables.version
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
if (unRegisteredDeps.length !== 0) {
|
|
72
|
+
console.log('\n Dependencies Risk Report', '\n\n Private libraries that are not scoped. We recommend these libraries are reviewed and the scope claimed to prevent dependency confusion breaches');
|
|
73
|
+
}
|
|
74
|
+
return unRegisteredDeps;
|
|
75
|
+
};
|
|
76
|
+
const createLibraryHeader = (id, numberOfVulnerableLibraries, numberOfCves, name) => {
|
|
77
|
+
name
|
|
78
|
+
? console.log(` Application Name: ${name} | Application ID: ${id}`)
|
|
79
|
+
: console.log(` Application ID: ${id}`);
|
|
80
|
+
console.log(` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's`);
|
|
81
|
+
};
|
|
82
|
+
const breakPipeline = () => {
|
|
83
|
+
failOptionError();
|
|
84
|
+
process.exit(1);
|
|
85
|
+
};
|
|
86
|
+
const parameterOptions = hasSomeVulnerabilitiesReported => {
|
|
87
|
+
const inputtedCLIOptions = cliOptions.getCommandLineArgs();
|
|
88
|
+
let cveSeverityOption = inputtedCLIOptions['cve_severity'];
|
|
89
|
+
let fail = inputtedCLIOptions['fail'];
|
|
90
|
+
let cve_threshold = inputtedCLIOptions['cve_threshold'];
|
|
91
|
+
let expr;
|
|
92
|
+
if (cveSeverityOption && fail && cve_threshold) {
|
|
93
|
+
expr = 'SeverityAndThreshold';
|
|
94
|
+
}
|
|
95
|
+
else if (!cveSeverityOption && fail && cve_threshold) {
|
|
96
|
+
expr = 'ThresholdOnly';
|
|
97
|
+
}
|
|
98
|
+
else if (!cve_threshold && fail && hasSomeVulnerabilitiesReported[0]) {
|
|
99
|
+
expr = 'FailOnly';
|
|
100
|
+
}
|
|
101
|
+
return expr;
|
|
102
|
+
};
|
|
103
|
+
const analyseReportOptions = hasSomeVulnerabilitiesReported => {
|
|
104
|
+
const inputtedCLIOptions = cliOptions.getCommandLineArgs();
|
|
105
|
+
let cve_threshold = inputtedCLIOptions['cve_threshold'];
|
|
106
|
+
let cveSeverity;
|
|
107
|
+
let criticalSeverity;
|
|
108
|
+
let highSeverity;
|
|
109
|
+
let mediumSeverity;
|
|
110
|
+
let lowSeverity;
|
|
111
|
+
switch (parameterOptions(hasSomeVulnerabilitiesReported)) {
|
|
112
|
+
case 'SeverityAndThreshold':
|
|
113
|
+
cveSeverity = inputtedCLIOptions['cve_severity'].severity;
|
|
114
|
+
criticalSeverity = hasSomeVulnerabilitiesReported[2].critical;
|
|
115
|
+
highSeverity = hasSomeVulnerabilitiesReported[2].high;
|
|
116
|
+
mediumSeverity = hasSomeVulnerabilitiesReported[2].medium;
|
|
117
|
+
lowSeverity = hasSomeVulnerabilitiesReported[2].low;
|
|
118
|
+
if (cveSeverity === 'HIGH') {
|
|
119
|
+
if (cve_threshold < highSeverity + criticalSeverity) {
|
|
120
|
+
breakPipeline();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (cveSeverity === 'MEDIUM') {
|
|
124
|
+
if (cve_threshold < mediumSeverity + highSeverity) {
|
|
125
|
+
breakPipeline();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (cveSeverity === 'LOW') {
|
|
129
|
+
if (cve_threshold < lowSeverity + mediumSeverity + highSeverity) {
|
|
130
|
+
breakPipeline();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
case 'ThresholdOnly':
|
|
135
|
+
if (cve_threshold < hasSomeVulnerabilitiesReported[1]) {
|
|
136
|
+
breakPipeline();
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case 'FailOnly':
|
|
140
|
+
breakPipeline();
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const getReport = async (applicationId) => {
|
|
145
|
+
const userParams = await util.getParams(applicationId);
|
|
146
|
+
const addParams = agent.getAdditionalParams();
|
|
147
|
+
const protocol = getValidHost(userParams.host);
|
|
148
|
+
const client = commonApi.getHttpClient(userParams, protocol, addParams);
|
|
149
|
+
return client
|
|
150
|
+
.getReport(userParams)
|
|
151
|
+
.then(res => {
|
|
152
|
+
if (res.statusCode === 200) {
|
|
153
|
+
displaySuccessMessageReport();
|
|
154
|
+
return res.body;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
handleResponseErrors(res, 'report');
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
.catch(err => {
|
|
161
|
+
console.log(err);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const printVulnerabilityResponse = (severity, filteredVulns, vulnerabilities) => {
|
|
165
|
+
let hasSomeVulnerabilitiesReported = false;
|
|
166
|
+
if (severity) {
|
|
167
|
+
returnCveData(filteredVulns);
|
|
168
|
+
if (Object.keys(filteredVulns).length > 0)
|
|
169
|
+
hasSomeVulnerabilitiesReported = true;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
returnCveData(vulnerabilities);
|
|
173
|
+
if (Object.keys(vulnerabilities).length > 0)
|
|
174
|
+
hasSomeVulnerabilitiesReported = true;
|
|
175
|
+
}
|
|
176
|
+
return hasSomeVulnerabilitiesReported;
|
|
177
|
+
};
|
|
178
|
+
const returnCveData = libraries => {
|
|
179
|
+
console.log('\n ************************************************************');
|
|
180
|
+
for (const [key, value] of Object.entries(libraries)) {
|
|
181
|
+
const parts = key.split('/');
|
|
182
|
+
const nameVersion = parts[1].split('@');
|
|
183
|
+
const group = parts[0];
|
|
184
|
+
const name = nameVersion[0];
|
|
185
|
+
const version = nameVersion[1];
|
|
186
|
+
const libName = group !== 'null'
|
|
187
|
+
? `${group}/${name}/${version} is vulnerable`
|
|
188
|
+
: `${name}/${version} is vulnerable`;
|
|
189
|
+
console.log('\n\n ' + libName);
|
|
190
|
+
value.forEach(vuln => {
|
|
191
|
+
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
192
|
+
console.log('\n ' + vuln.name + ' ' + sevCode + '\n ' + vuln.description);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
function searchHighCVEs(vuln) {
|
|
197
|
+
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
198
|
+
if (sevCode === 'HIGH') {
|
|
199
|
+
return vuln;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function searchMediumCVEs(vuln) {
|
|
203
|
+
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
204
|
+
if (sevCode === 'HIGH' || sevCode === 'MEDIUM') {
|
|
205
|
+
return vuln;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function searchLowCVEs(vuln) {
|
|
209
|
+
let sevCode = vuln.severityCode || vuln.severity_code;
|
|
210
|
+
if (sevCode === 'HIGH' || sevCode === 'MEDIUM' || sevCode === 'LOW') {
|
|
211
|
+
return vuln;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const filterVulnerabilitiesBySeverity = (severity, vulnerabilities) => {
|
|
215
|
+
let filteredVulns = [];
|
|
216
|
+
if (severity) {
|
|
217
|
+
for (let x in vulnerabilities) {
|
|
218
|
+
if (severity.severity === 'HIGH') {
|
|
219
|
+
let highVulnerability = vulnerabilities[x].filter(searchHighCVEs);
|
|
220
|
+
if (highVulnerability.length > 0) {
|
|
221
|
+
filteredVulns[x] = highVulnerability;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (severity.severity === 'MEDIUM') {
|
|
225
|
+
let mediumVulnerability = vulnerabilities[x].filter(searchMediumCVEs);
|
|
226
|
+
if (mediumVulnerability.length > 0) {
|
|
227
|
+
filteredVulns[x] = mediumVulnerability;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (severity.severity === 'LOW') {
|
|
231
|
+
let lowVulnerability = vulnerabilities[x].filter(searchLowCVEs);
|
|
232
|
+
if (lowVulnerability.length > 0) {
|
|
233
|
+
filteredVulns[x] = lowVulnerability;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return filteredVulns;
|
|
239
|
+
};
|
|
240
|
+
module.exports = {
|
|
241
|
+
displaySuccessMessageReport: displaySuccessMessageReport,
|
|
242
|
+
getAllDependenciesArray: getAllDependenciesArray,
|
|
243
|
+
dependencyRiskReport: dependencyRiskReport,
|
|
244
|
+
createLibraryHeader: createLibraryHeader,
|
|
245
|
+
breakPipeline: breakPipeline,
|
|
246
|
+
parameterOptions: parameterOptions,
|
|
247
|
+
analyseReportOptions: analyseReportOptions,
|
|
248
|
+
getReport: getReport,
|
|
249
|
+
checkIfDepIsScoped: checkIfDepIsScoped,
|
|
250
|
+
checkIfDepIsRegisteredOnNPM: checkIfDepIsRegisteredOnNPM,
|
|
251
|
+
filterVulnerabilitiesBySeverity: filterVulnerabilitiesBySeverity,
|
|
252
|
+
searchLowCVEs: searchLowCVEs,
|
|
253
|
+
searchMediumCVEs: searchMediumCVEs,
|
|
254
|
+
searchHighCVEs: searchHighCVEs,
|
|
255
|
+
returnCveData: returnCveData,
|
|
256
|
+
printVulnerabilityResponse: printVulnerabilityResponse
|
|
257
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const commonReport = require('./commonReportingFunctions');
|
|
3
|
+
const { handleResponseErrors } = require('../commonApi');
|
|
4
|
+
const { getHttpClient } = require('../../../utils/commonApi');
|
|
5
|
+
const vulnReportWithoutDevDep = async (analysis, applicationId, snapshotId, config) => {
|
|
6
|
+
if (config.report) {
|
|
7
|
+
const reportResponse = await getSpecReport(snapshotId, config);
|
|
8
|
+
if (reportResponse !== undefined) {
|
|
9
|
+
const severity = config.cveSeverity;
|
|
10
|
+
const id = applicationId;
|
|
11
|
+
const name = config.applicationName;
|
|
12
|
+
const hasSomeVulnerabilitiesReported = formatVulnerabilityOutput(reportResponse.vulnerabilities, severity, id, name, config);
|
|
13
|
+
commonReport.analyseReportOptions(hasSomeVulnerabilitiesReported);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const getSpecReport = async (reportId, config) => {
|
|
18
|
+
const client = getHttpClient(config);
|
|
19
|
+
return client
|
|
20
|
+
.getSpecificReport(config, reportId)
|
|
21
|
+
.then(res => {
|
|
22
|
+
if (res.statusCode === 200) {
|
|
23
|
+
commonReport.displaySuccessMessageReport();
|
|
24
|
+
return res.body;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
handleResponseErrors(res, 'report');
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.catch(err => {
|
|
31
|
+
console.log(err);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
const countSeverity = vulnerabilities => {
|
|
35
|
+
const severityCount = {
|
|
36
|
+
critical: 0,
|
|
37
|
+
high: 0,
|
|
38
|
+
medium: 0,
|
|
39
|
+
low: 0
|
|
40
|
+
};
|
|
41
|
+
for (const key of Object.keys(vulnerabilities)) {
|
|
42
|
+
vulnerabilities[key].forEach(vuln => {
|
|
43
|
+
if (vuln.severityCode === 'HIGH') {
|
|
44
|
+
severityCount['high'] += 1;
|
|
45
|
+
}
|
|
46
|
+
else if (vuln.severityCode === 'MEDIUM') {
|
|
47
|
+
severityCount['medium'] += 1;
|
|
48
|
+
}
|
|
49
|
+
else if (vuln.severityCode === 'LOW') {
|
|
50
|
+
severityCount['low'] += 1;
|
|
51
|
+
}
|
|
52
|
+
else if (vuln.severityCode === 'CRITICAL') {
|
|
53
|
+
severityCount['critical'] += 1;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return severityCount;
|
|
58
|
+
};
|
|
59
|
+
const formatVulnerabilityOutput = (vulnerabilities, severity, id, name, config) => {
|
|
60
|
+
const numberOfVulnerableLibraries = Object.keys(vulnerabilities).length;
|
|
61
|
+
let numberOfCves = 0;
|
|
62
|
+
for (const key of Object.keys(vulnerabilities)) {
|
|
63
|
+
numberOfCves += vulnerabilities[key].length;
|
|
64
|
+
}
|
|
65
|
+
commonReport.createLibraryHeader(id, numberOfVulnerableLibraries, numberOfCves, name);
|
|
66
|
+
const severityCount = countSeverity(vulnerabilities);
|
|
67
|
+
const filteredVulns = commonReport.filterVulnerabilitiesBySeverity(severity, vulnerabilities);
|
|
68
|
+
let hasSomeVulnerabilitiesReported;
|
|
69
|
+
hasSomeVulnerabilitiesReported = commonReport.printVulnerabilityResponse(severity, filteredVulns, vulnerabilities);
|
|
70
|
+
console.log('\n **************************' +
|
|
71
|
+
` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's ` +
|
|
72
|
+
'************************** ');
|
|
73
|
+
console.log(' \n Please go to the Contrast UI to view your dependency tree: \n' +
|
|
74
|
+
` \n ${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
|
|
75
|
+
return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount];
|
|
76
|
+
};
|
|
77
|
+
module.exports = {
|
|
78
|
+
vulnReportWithoutDevDep: vulnReportWithoutDevDep,
|
|
79
|
+
formatVulnerabilityOutput: formatVulnerabilityOutput,
|
|
80
|
+
getSpecReport: getSpecReport
|
|
81
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const i18n = require('i18n');
|
|
3
|
+
const commonApi = require('../commonApi');
|
|
4
|
+
const commonReport = require('./commonReportingFunctions');
|
|
5
|
+
function displaySuccessMessageVulnerabilities() {
|
|
6
|
+
console.log(i18n.__('vulnerabilitiesSuccessMessage'));
|
|
7
|
+
}
|
|
8
|
+
const vulnerabilityReport = async (analysis, applicationId, config) => {
|
|
9
|
+
let depRiskReportCount = {};
|
|
10
|
+
if (analysis.language === 'NODE') {
|
|
11
|
+
depRiskReportCount = await commonReport.dependencyRiskReport(analysis.node.packageJSON, config);
|
|
12
|
+
}
|
|
13
|
+
if (config['report']) {
|
|
14
|
+
const reportResponse = await commonReport.getReport(applicationId);
|
|
15
|
+
if (reportResponse !== undefined) {
|
|
16
|
+
const libraryVulnerabilityInput = createLibraryVulnerabilityInput(reportResponse.reports);
|
|
17
|
+
const libraryVulnerabilityResponse = await getLibraryVulnerabilities(libraryVulnerabilityInput, applicationId);
|
|
18
|
+
const severity = config['cve_severity'];
|
|
19
|
+
const id = applicationId;
|
|
20
|
+
const name = config.applicationName;
|
|
21
|
+
const hasSomeVulnerabilitiesReported = formatVulnerabilityOutput(libraryVulnerabilityResponse, severity, id, name, depRiskReportCount, config);
|
|
22
|
+
commonReport.analyseReportOptions(hasSomeVulnerabilitiesReported);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const createLibraryVulnerabilityInput = report => {
|
|
27
|
+
const language = Object.keys(report[0].report)[0];
|
|
28
|
+
const reportTree = report[0].report[language].dependencyTree;
|
|
29
|
+
const libraries = reportTree[Object.keys(reportTree)[0]];
|
|
30
|
+
let gav = [];
|
|
31
|
+
for (const key of Object.keys(libraries)) {
|
|
32
|
+
gav.push({
|
|
33
|
+
name: libraries[key].name,
|
|
34
|
+
group: libraries[key].group,
|
|
35
|
+
version: libraries[key].resolved
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
name_group_versions: gav,
|
|
40
|
+
language: language.toUpperCase()
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const oldCountSeverity = vulnerableLibraries => {
|
|
44
|
+
const severityCount = {
|
|
45
|
+
critical: 0,
|
|
46
|
+
high: 0,
|
|
47
|
+
medium: 0,
|
|
48
|
+
low: 0
|
|
49
|
+
};
|
|
50
|
+
vulnerableLibraries.forEach(lib => {
|
|
51
|
+
lib.vulns.forEach(vuln => {
|
|
52
|
+
if (vuln.severity_code === 'HIGH') {
|
|
53
|
+
severityCount['high'] += 1;
|
|
54
|
+
}
|
|
55
|
+
else if (vuln.severity_code === 'MEDIUM') {
|
|
56
|
+
severityCount['medium'] += 1;
|
|
57
|
+
}
|
|
58
|
+
else if (vuln.severity_code === 'LOW') {
|
|
59
|
+
severityCount['low'] += 1;
|
|
60
|
+
}
|
|
61
|
+
else if (vuln.severity_code === 'CRITICAL') {
|
|
62
|
+
severityCount['critical'] += 1;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return severityCount;
|
|
67
|
+
};
|
|
68
|
+
const parseVulnerabilites = libraryVulnerabilityResponse => {
|
|
69
|
+
let parsedVulnerabilites = {};
|
|
70
|
+
let vulnName = libraryVulnerabilityResponse.libraries;
|
|
71
|
+
for (let x in vulnName) {
|
|
72
|
+
let vuln = vulnName[x].vulns;
|
|
73
|
+
if (vuln.length > 0) {
|
|
74
|
+
let libname = vulnName[x].group +
|
|
75
|
+
'/' +
|
|
76
|
+
vulnName[x].file_name +
|
|
77
|
+
'@' +
|
|
78
|
+
vulnName[x].file_version;
|
|
79
|
+
parsedVulnerabilites[libname] = vulnName[x].vulns;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return parsedVulnerabilites;
|
|
83
|
+
};
|
|
84
|
+
const formatVulnerabilityOutput = (libraryVulnerabilityResponse, severity, id, name, depRiskReportCount, config) => {
|
|
85
|
+
let vulnerableLibraries = libraryVulnerabilityResponse.libraries.filter(data => {
|
|
86
|
+
return data.vulns.length > 0;
|
|
87
|
+
});
|
|
88
|
+
const numberOfVulnerableLibraries = vulnerableLibraries.length;
|
|
89
|
+
let numberOfCves = 0;
|
|
90
|
+
vulnerableLibraries.forEach(lib => (numberOfCves += lib.vulns.length));
|
|
91
|
+
commonReport.createLibraryHeader(id, numberOfVulnerableLibraries, numberOfCves, name);
|
|
92
|
+
const severityCount = oldCountSeverity(vulnerableLibraries);
|
|
93
|
+
let vulnerabilities = parseVulnerabilites(libraryVulnerabilityResponse);
|
|
94
|
+
let filteredVulns = commonReport.filterVulnerabilitiesBySeverity(severity, vulnerabilities);
|
|
95
|
+
let hasSomeVulnerabilitiesReported;
|
|
96
|
+
hasSomeVulnerabilitiesReported = commonReport.printVulnerabilityResponse(severity, filteredVulns, vulnerabilities);
|
|
97
|
+
console.log('\n **************************' +
|
|
98
|
+
` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's ` +
|
|
99
|
+
'************************** ');
|
|
100
|
+
if (depRiskReportCount && depRiskReportCount.scopedCount === 0) {
|
|
101
|
+
console.log(' No private libraries that are not scoped detected');
|
|
102
|
+
}
|
|
103
|
+
console.log(' \n Please go to the Contrast UI to view your dependency tree: \n' +
|
|
104
|
+
` \n ${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
|
|
105
|
+
return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount];
|
|
106
|
+
};
|
|
107
|
+
const getLibraryVulnerabilities = async (input, applicationId) => {
|
|
108
|
+
const requestBody = input;
|
|
109
|
+
const addParams = agent.getAdditionalParams();
|
|
110
|
+
const userParams = await util.getParams(applicationId);
|
|
111
|
+
const protocol = getValidHost(userParams.host);
|
|
112
|
+
const client = commonApi.getHttpClient(userParams, protocol, addParams);
|
|
113
|
+
return client
|
|
114
|
+
.getLibraryVulnerabilities(requestBody, userParams)
|
|
115
|
+
.then(res => {
|
|
116
|
+
if (res.statusCode === 200) {
|
|
117
|
+
displaySuccessMessageVulnerabilities();
|
|
118
|
+
return res.body;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
handleResponseErrors(res, 'vulnerabilities');
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
.catch(err => {
|
|
125
|
+
console.log(err);
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
module.exports = {
|
|
129
|
+
vulnerabilityReport: vulnerabilityReport,
|
|
130
|
+
getLibraryVulnerabilities: getLibraryVulnerabilities,
|
|
131
|
+
formatVulnerabilityOutput: formatVulnerabilityOutput,
|
|
132
|
+
createLibraryVulnerabilityInput: createLibraryVulnerabilityInput
|
|
133
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const prettyjson = require('prettyjson');
|
|
3
|
+
const i18n = require('i18n');
|
|
4
|
+
const { getHttpClient } = require('../../utils/commonApi');
|
|
5
|
+
const { handleResponseErrors } = require('../../common/errorHandling');
|
|
6
|
+
const { APP_VERSION } = require('../../constants/constants');
|
|
7
|
+
function displaySnapshotSuccessMessage(config) {
|
|
8
|
+
console.log('\n **************************' +
|
|
9
|
+
i18n.__('successHeader') +
|
|
10
|
+
'************************** ');
|
|
11
|
+
console.log('\n' + i18n.__('snapshotSuccessMessage') + '\n');
|
|
12
|
+
console.log(` ${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
|
|
13
|
+
console.log('\n ***********************************************************');
|
|
14
|
+
}
|
|
15
|
+
const newSendSnapShot = async (analysis, applicationId) => {
|
|
16
|
+
const analysisLanguage = analysis.config.language.toLowerCase();
|
|
17
|
+
const requestBody = {
|
|
18
|
+
appID: analysis.config.applicationId,
|
|
19
|
+
cliVersion: APP_VERSION,
|
|
20
|
+
snapshot: { [analysisLanguage]: analysis[analysisLanguage] }
|
|
21
|
+
};
|
|
22
|
+
const client = getHttpClient(analysis.config);
|
|
23
|
+
return client
|
|
24
|
+
.sendSnapshot(requestBody, analysis.config)
|
|
25
|
+
.then(res => {
|
|
26
|
+
if (res.statusCode === 201) {
|
|
27
|
+
displaySnapshotSuccessMessage(analysis.config);
|
|
28
|
+
return res.body;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
handleResponseErrors(res, 'snapshot');
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.catch(err => {
|
|
35
|
+
console.log(err);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
module.exports = {
|
|
39
|
+
newSendSnapShot: newSendSnapShot,
|
|
40
|
+
displaySnapshotSuccessMessage: displaySnapshotSuccessMessage
|
|
41
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { featuresTeamServer } = require('./capabilities');
|
|
3
|
+
const semver = require('semver');
|
|
4
|
+
const { handleResponseErrors } = require('../../../common/errorHandling');
|
|
5
|
+
const { getHttpClient } = require('../../../utils/commonApi');
|
|
6
|
+
const getGlobalProperties = async (config) => {
|
|
7
|
+
const client = getHttpClient(config);
|
|
8
|
+
return client
|
|
9
|
+
.getGlobalProperties(config)
|
|
10
|
+
.then(res => {
|
|
11
|
+
if (res.statusCode === 200) {
|
|
12
|
+
return res.body;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
handleResponseErrors(res, 'globalProperties');
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
.catch(err => {
|
|
19
|
+
console.log(err);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const getFeatures = version => {
|
|
23
|
+
const featuresEnabled = [];
|
|
24
|
+
featuresTeamServer.forEach(feature => {
|
|
25
|
+
const versionFrom = Object.values(feature)[0];
|
|
26
|
+
return semver.gte(version, versionFrom)
|
|
27
|
+
? featuresEnabled.push(Object.keys(feature)[0])
|
|
28
|
+
: null;
|
|
29
|
+
});
|
|
30
|
+
return featuresEnabled;
|
|
31
|
+
};
|
|
32
|
+
const isFeatureEnabled = (features, featureName) => {
|
|
33
|
+
return features.includes(featureName);
|
|
34
|
+
};
|
|
35
|
+
module.exports = {
|
|
36
|
+
getGlobalProperties,
|
|
37
|
+
getFeatures,
|
|
38
|
+
isFeatureEnabled
|
|
39
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const request = require('request');
|
|
3
|
+
const Promise = require('bluebird');
|
|
4
|
+
Promise.promisifyAll(request);
|
|
5
|
+
function sendRequest({ options, method = 'put' }) {
|
|
6
|
+
return request[`${method}Async`](options.url, options);
|
|
7
|
+
}
|
|
8
|
+
const sleep = ms => {
|
|
9
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
10
|
+
};
|
|
11
|
+
module.exports = {
|
|
12
|
+
sendRequest: sendRequest,
|
|
13
|
+
sleep: sleep
|
|
14
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const i18n = require('i18n');
|
|
3
|
+
module.exports = exports = (analysis, next) => {
|
|
4
|
+
const { language: { lockFilePath }, node } = analysis;
|
|
5
|
+
try {
|
|
6
|
+
if (node.npmLockFile && node.npmLockFile.lockfileVersion > 1) {
|
|
7
|
+
const listOfTopDep = Object.keys(node.npmLockFile.dependencies);
|
|
8
|
+
Object.entries(node.npmLockFile.dependencies).forEach(([key, value]) => {
|
|
9
|
+
if (value.requires) {
|
|
10
|
+
const listOfRequiresDep = Object.keys(value.requires);
|
|
11
|
+
listOfRequiresDep.forEach(dep => {
|
|
12
|
+
if (!listOfTopDep.includes(dep)) {
|
|
13
|
+
addDepToLockFile(value['requires'], dep);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (value.dependencies) {
|
|
18
|
+
Object.entries(value.dependencies).forEach(([childKey, childValue]) => {
|
|
19
|
+
if (childValue.requires) {
|
|
20
|
+
const listOfRequiresDep = Object.keys(childValue.requires);
|
|
21
|
+
listOfRequiresDep.forEach(dep => {
|
|
22
|
+
if (!listOfTopDep.includes(dep)) {
|
|
23
|
+
addDepToLockFile(childValue['requires'], dep);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
next(next(new Error(i18n.__('NodeParseNPM', lockFilePath) + `${err.message}`)));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
function addDepToLockFile(depObj, key) {
|
|
37
|
+
node.npmLockFile.dependencies[key] = { version: depObj[key] };
|
|
38
|
+
}
|
|
39
|
+
next();
|
|
40
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const AnalysisEngine = require('../AnalysisEngine');
|
|
3
|
+
const readProjectFileContents = require('./readProjectFileContents');
|
|
4
|
+
const readNPMLockFileContents = require('./readNPMLockFileContents');
|
|
5
|
+
const parseNPMLockFileContents = require('./parseNPMLockFileContents');
|
|
6
|
+
const readYarnLockFileContents = require('./readYarnLockFileContents');
|
|
7
|
+
const parseYarnLockFileContents = require('./parseYarnLockFileContents');
|
|
8
|
+
const parseYarn2LockFileContents = require('./parseYarn2LockFileContents');
|
|
9
|
+
const handleNPMLockFileV2 = require('./handleNPMLockFileV2');
|
|
10
|
+
const sanitizer = require('./sanitizer');
|
|
11
|
+
const i18n = require('i18n');
|
|
12
|
+
module.exports = exports = (language, config, callback) => {
|
|
13
|
+
const ae = new AnalysisEngine({ language, config, node: {} });
|
|
14
|
+
ae.use([
|
|
15
|
+
readProjectFileContents,
|
|
16
|
+
readNPMLockFileContents,
|
|
17
|
+
parseNPMLockFileContents,
|
|
18
|
+
readYarnLockFileContents,
|
|
19
|
+
parseYarnLockFileContents,
|
|
20
|
+
parseYarn2LockFileContents,
|
|
21
|
+
handleNPMLockFileV2,
|
|
22
|
+
sanitizer
|
|
23
|
+
]);
|
|
24
|
+
ae.analyze((err, analysis) => {
|
|
25
|
+
if (err) {
|
|
26
|
+
callback(new Error(i18n.__('NodeAnalysisFailure') + `${err.message}`));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
callback(null, analysis);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const i18n = require('i18n');
|
|
3
|
+
module.exports = exports = ({ language: { lockFilePath }, node }, next) => {
|
|
4
|
+
if (node.rawLockFileContents === undefined) {
|
|
5
|
+
next();
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
try {
|
|
9
|
+
node.npmLockFile = JSON.parse(node.rawLockFileContents);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
next(new Error(i18n.__('NodeParseNPM', lockFilePath ? lockFilePath : 'undefined') +
|
|
13
|
+
`${err.message}`));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
next();
|
|
17
|
+
}
|
|
18
|
+
};
|