snyk-nuget-plugin 1.8.0 → 1.10.0
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/.eslintrc +1 -1
- package/README.md +1 -1
- package/lib/index.js +10 -11
- package/lib/nuget-parser/csproj-parser.js +75 -0
- package/lib/{dependency.js → nuget-parser/dependency.js} +1 -0
- package/lib/{formats → nuget-parser}/dotnet-core-parser.js +61 -46
- package/lib/nuget-parser/dotnet-framework-parser.js +140 -0
- package/lib/nuget-parser/index.js +88 -0
- package/lib/{nuspec-parser.js → nuget-parser/nuspec-parser.js} +20 -19
- package/lib/nuget-parser/packages-config-parser.js +28 -0
- package/lib/nuget-parser/project-json-parser.js +73 -0
- package/package.json +1 -1
- package/lib/dotnet-parser.js +0 -231
- package/lib/find-folder.js +0 -16
- package/lib/json-manifest-parser.js +0 -46
- package/lib/proj-parser.js +0 -75
package/.eslintrc
CHANGED
package/README.md
CHANGED
|
@@ -8,4 +8,4 @@ Snyk helps you find, fix and monitor for known vulnerabilities in your dependenc
|
|
|
8
8
|
|
|
9
9
|
## Snyk NuGet CLI Plugin
|
|
10
10
|
|
|
11
|
-
The plugin provides dependency metadata for NuGet projects that manifest dependencies in `project.json` or `
|
|
11
|
+
The plugin provides dependency metadata for NuGet projects that manifest dependencies in `project.json`, `packages.config` or `project.assets.json` files.
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const nugetParser = require('./nuget-parser');
|
|
4
|
+
const paketParser = require('snyk-paket-parser');
|
|
4
5
|
|
|
5
6
|
function determineManifestType(filename) {
|
|
6
7
|
switch (true) {
|
|
@@ -25,16 +26,15 @@ function determineManifestType(filename) {
|
|
|
25
26
|
module.exports = {
|
|
26
27
|
inspect: function (root, targetFile, options) {
|
|
27
28
|
options = options || {};
|
|
28
|
-
|
|
29
|
-
var manifestType;
|
|
29
|
+
let manifestType;
|
|
30
30
|
try {
|
|
31
31
|
manifestType = determineManifestType(path.basename(targetFile || root));
|
|
32
32
|
} catch (error) {
|
|
33
33
|
return Promise.reject(error);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const createPackageTree = function (depTree) {
|
|
37
|
+
const targetFramework = depTree.meta ? depTree.meta.targetFramework : undefined; // TODO implement for paket and more than one framework
|
|
38
38
|
delete depTree.meta;
|
|
39
39
|
return {
|
|
40
40
|
package: depTree,
|
|
@@ -56,12 +56,11 @@ module.exports = {
|
|
|
56
56
|
).then(createPackageTree);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
return
|
|
59
|
+
return nugetParser.buildDepTreeFromFiles(
|
|
60
60
|
root,
|
|
61
61
|
targetFile,
|
|
62
62
|
options.packagesFolder,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
manifestType,
|
|
64
|
+
options['assets-project-name']).then(createPackageTree);
|
|
66
65
|
},
|
|
67
66
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const parseXML = require('xml2js').parseString;
|
|
5
|
+
const debug = require('debug')('snyk');
|
|
6
|
+
const _ = require('lodash');
|
|
7
|
+
|
|
8
|
+
function getTargetFrameworksFromProjFile(rootDir) {
|
|
9
|
+
debug('Looking for your .csproj file in ' + rootDir);
|
|
10
|
+
const csprojPath = findFile(rootDir, /.*\.csproj$/);
|
|
11
|
+
if (csprojPath) {
|
|
12
|
+
debug('Checking .net framework version in .csproj file ' + csprojPath);
|
|
13
|
+
|
|
14
|
+
const csprojContents = fs.readFileSync(csprojPath);
|
|
15
|
+
|
|
16
|
+
let frameworks = [];
|
|
17
|
+
parseXML(csprojContents, function (err, parsedCsprojContents) {
|
|
18
|
+
if (err) {
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
const versionLoc = _.get(parsedCsprojContents, 'Project.PropertyGroup[0]');
|
|
22
|
+
const versions = _.compact(_.concat([],
|
|
23
|
+
_.get(versionLoc, 'TargetFrameworkVersion[0]') ||
|
|
24
|
+
_.get(versionLoc, 'TargetFramework[0]') ||
|
|
25
|
+
_.get(versionLoc, 'TargetFrameworks[0]', '').split(';')));
|
|
26
|
+
|
|
27
|
+
if (versions.length < 1) {
|
|
28
|
+
debug('Could not find TargetFrameworkVersion/TargetFramework' +
|
|
29
|
+
'/TargetFrameworks defined in the Project.PropertyGroup field of ' +
|
|
30
|
+
'your .csproj file');
|
|
31
|
+
}
|
|
32
|
+
frameworks = _.compact(_.map(versions, toReadableFramework));
|
|
33
|
+
if (versions.length > 1 && frameworks.length < 1) {
|
|
34
|
+
debug('Could not find valid/supported .NET version in csproj file located at' + csprojPath);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return frameworks[0];
|
|
38
|
+
}
|
|
39
|
+
debug('.csproj file not found in ' + rootDir + '.');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function toReadableFramework(targetFramework) {
|
|
43
|
+
const typeMapping = {
|
|
44
|
+
v: '.NETFramework',
|
|
45
|
+
net: '.NETFramework',
|
|
46
|
+
netstandard: '.NETStandard',
|
|
47
|
+
netcoreapp: '.NETCore',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
for (const type in typeMapping) {
|
|
51
|
+
if (new RegExp(type + /\d.?\d(.?\d)?$/.source).test(targetFramework)) {
|
|
52
|
+
return {
|
|
53
|
+
framework: typeMapping[type],
|
|
54
|
+
version: targetFramework.split(type)[1],
|
|
55
|
+
original: targetFramework,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function findFile(rootDir, filter) {
|
|
62
|
+
if (!fs.existsSync(rootDir)) {
|
|
63
|
+
throw new Error('No such path: ' + rootDir);
|
|
64
|
+
}
|
|
65
|
+
const files = fs.readdirSync(rootDir);
|
|
66
|
+
for (let i = 0; i < files.length; i++) {
|
|
67
|
+
const filename = path.resolve(rootDir, files[i]);
|
|
68
|
+
|
|
69
|
+
if (filter.test(filename)) {
|
|
70
|
+
return filename;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = getTargetFrameworksFromProjFile;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
const Dependency = require('../nuget-parser/dependency');
|
|
3
|
+
const debug = require('debug')('snyk');
|
|
4
|
+
const _ = require('lodash');
|
|
5
5
|
|
|
6
6
|
// TODO: any convention for global vars? (gFreqDeps)
|
|
7
7
|
let freqDeps = {};
|
|
@@ -84,16 +84,8 @@ function buildTreeRecursive(targetDeps, depName, parent, treeDepth) {
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
function getFrameworkObjToRun(manifest) {
|
|
87
|
+
function getFrameworkToRun(manifest) {
|
|
89
88
|
const frameworks = _.get(manifest, 'project.frameworks');
|
|
90
|
-
if (!frameworks) {
|
|
91
|
-
throw new Error('No frameworks were found in project.assets.json');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (_.isEmpty(frameworks)) {
|
|
95
|
-
throw new Error('0 frameworks were found in project.assets.json');
|
|
96
|
-
}
|
|
97
89
|
|
|
98
90
|
debug(`Available frameworks: '${Object.keys(frameworks)}'`);
|
|
99
91
|
|
|
@@ -101,19 +93,10 @@ function getFrameworkObjToRun(manifest) {
|
|
|
101
93
|
// taking only the first 1
|
|
102
94
|
const selectedFrameworkKey = Object.keys(frameworks)[0];
|
|
103
95
|
debug(`Selected framework: '${selectedFrameworkKey}'`);
|
|
104
|
-
return
|
|
96
|
+
return selectedFrameworkKey;
|
|
105
97
|
}
|
|
106
98
|
|
|
107
|
-
|
|
108
99
|
function getTargetObjToRun(manifest) {
|
|
109
|
-
if (!manifest.targets) {
|
|
110
|
-
throw new Error('No targets were found in project.assets.json');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (_.isEmpty(manifest.targets)) {
|
|
114
|
-
throw new Error('0 targets were found in project.assets.json');
|
|
115
|
-
}
|
|
116
|
-
|
|
117
100
|
debug(`Available targets: '${Object.keys(manifest.targets)}'`);
|
|
118
101
|
|
|
119
102
|
let selectedTargetKey = Object.keys(manifest.targets)[0];
|
|
@@ -123,38 +106,70 @@ function getTargetObjToRun(manifest) {
|
|
|
123
106
|
return manifest.targets[selectedTargetKey];
|
|
124
107
|
}
|
|
125
108
|
|
|
126
|
-
|
|
127
|
-
function parse(fileContent, packageTree) {
|
|
128
|
-
const manifest = JSON.parse(fileContent);
|
|
129
|
-
|
|
109
|
+
function validateManifest(manifest) {
|
|
130
110
|
if (!manifest.project) {
|
|
131
111
|
throw new Error('Project field was not found in project.assets.json');
|
|
132
112
|
}
|
|
133
113
|
|
|
134
|
-
if (manifest.project.
|
|
135
|
-
|
|
114
|
+
if (!manifest.project.frameworks) {
|
|
115
|
+
throw new Error('No frameworks were found in project.assets.json');
|
|
136
116
|
}
|
|
137
117
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
initFreqDepsDict();
|
|
142
|
-
|
|
143
|
-
const directDependencies = collectFlatList(selectedFrameworkObj.dependencies);
|
|
144
|
-
debug(`directDependencies: '${directDependencies}'`);
|
|
118
|
+
if (_.isEmpty(manifest.project.frameworks)) {
|
|
119
|
+
throw new Error('0 frameworks were found in project.assets.json');
|
|
120
|
+
}
|
|
145
121
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
});
|
|
122
|
+
if (!manifest.targets) {
|
|
123
|
+
throw new Error('No targets were found in project.assets.json');
|
|
124
|
+
}
|
|
150
125
|
|
|
151
|
-
if (
|
|
152
|
-
|
|
126
|
+
if (_.isEmpty(manifest.targets)) {
|
|
127
|
+
throw new Error('0 targets were found in project.assets.json');
|
|
153
128
|
}
|
|
154
|
-
// to disconnect the object references inside the tree
|
|
155
|
-
// JSON parse/stringify is used
|
|
156
|
-
let pathedTree = JSON.parse(JSON.stringify(packageTree.dependencies));
|
|
157
|
-
packageTree.dependencies = pathedTree;
|
|
158
129
|
}
|
|
159
130
|
|
|
160
|
-
module.exports =
|
|
131
|
+
module.exports = {
|
|
132
|
+
parse: function (tree, manifest) {
|
|
133
|
+
return new Promise(function parseFileContents(resolve, reject) {
|
|
134
|
+
debug('Trying to parse dot-net-cli manifest');
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
validateManifest(manifest);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
debug('Invalid project.assets.json manifest file');
|
|
140
|
+
reject(err);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (manifest.project.version) {
|
|
144
|
+
tree.version = manifest.project.version;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// If a targetFramework was not found in the proj file, we will extract it from the lock file
|
|
148
|
+
if (!tree.meta.targetFramework) {
|
|
149
|
+
tree.meta.targetFramework = getFrameworkToRun(manifest);
|
|
150
|
+
}
|
|
151
|
+
const selectedFrameworkObj = manifest.project.frameworks[tree.meta.targetFramework];
|
|
152
|
+
|
|
153
|
+
// We currently ignore the found targetFramework when looking for target dependencies
|
|
154
|
+
const selectedTargetObj = getTargetObjToRun(manifest);
|
|
155
|
+
|
|
156
|
+
initFreqDepsDict();
|
|
157
|
+
|
|
158
|
+
const directDependencies = collectFlatList(selectedFrameworkObj.dependencies);
|
|
159
|
+
debug(`directDependencies: '${directDependencies}'`);
|
|
160
|
+
|
|
161
|
+
directDependencies.forEach(function (directDep) {
|
|
162
|
+
debug(`First order dep: '${directDep}'`);
|
|
163
|
+
buildTreeRecursive(selectedTargetObj, directDep, tree, 0);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
if (!_.isEmpty(freqDeps.dependencies.dependencies)) {
|
|
167
|
+
tree.dependencies['freqSystemDependencies'] = freqDeps.dependencies;
|
|
168
|
+
}
|
|
169
|
+
// to disconnect the object references inside the tree
|
|
170
|
+
// JSON parse/stringify is used
|
|
171
|
+
tree.dependencies = JSON.parse(JSON.stringify(tree.dependencies));
|
|
172
|
+
resolve(tree);
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const debug = require('debug')('snyk');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const Dependency = require('./dependency');
|
|
6
|
+
const parseNuspec = require('./nuspec-parser');
|
|
7
|
+
const _ = require('lodash');
|
|
8
|
+
|
|
9
|
+
function injectPath(dep, packagesFolder) {
|
|
10
|
+
dep.path = dep.localPath ?
|
|
11
|
+
path.resolve(packagesFolder, dep.localPath)
|
|
12
|
+
: path.resolve(packagesFolder, dep.name + '.' + dep.version);
|
|
13
|
+
if (dep.localPath) {
|
|
14
|
+
delete dep.localPath;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function scanInstalled(installedPackages, packagesFolder) {
|
|
19
|
+
const flattenedPackageList = {};
|
|
20
|
+
debug('Located ' + installedPackages.length + ' packages in manifest');
|
|
21
|
+
installedPackages.forEach(function (entry) {
|
|
22
|
+
injectPath(entry, packagesFolder);
|
|
23
|
+
flattenedPackageList[entry.name] =
|
|
24
|
+
flattenedPackageList[entry.name] || entry;
|
|
25
|
+
debug('Entry: ' + entry.name + ' -> ' + entry.path);
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
debug('Scanning local installed folders');
|
|
29
|
+
debug('Trying to read from installed packages folder: ' + packagesFolder);
|
|
30
|
+
fs.readdirSync(packagesFolder)
|
|
31
|
+
.map(function (folderName) {
|
|
32
|
+
try {
|
|
33
|
+
return Dependency.from.folderName(folderName);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
debug('Unable to parse dependency from folder');
|
|
36
|
+
debug(err);
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
.forEach(function (dep) {
|
|
40
|
+
if (dep) {
|
|
41
|
+
injectPath(dep, packagesFolder);
|
|
42
|
+
// only add a package from packages folder if version is different
|
|
43
|
+
if (flattenedPackageList[dep.name] &&
|
|
44
|
+
flattenedPackageList[dep.name].version !== dep.version) {
|
|
45
|
+
// prefer found from packages folder (dep) over existing
|
|
46
|
+
debug('For package ' + dep.name + ' the version ' +
|
|
47
|
+
flattenedPackageList[dep.name].version +
|
|
48
|
+
' was extracted from manifest file.' +
|
|
49
|
+
'\nWe are overwriting it with version ' + dep.version +
|
|
50
|
+
' from the packages folder');
|
|
51
|
+
flattenedPackageList[dep.name] = dep;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} catch (err) {
|
|
56
|
+
debug('Could not complete packages folder scanning');
|
|
57
|
+
debug(err);
|
|
58
|
+
}
|
|
59
|
+
return flattenedPackageList;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function fetchNugetInformationFromPackages(flattenedPackageList, targetFramework) {
|
|
63
|
+
const nuspecParserChain = [];
|
|
64
|
+
// begin collecting information from .nuget files on installed packages
|
|
65
|
+
debug('Trying to analyze .nuspec files');
|
|
66
|
+
for (const name in flattenedPackageList) {
|
|
67
|
+
const dep = flattenedPackageList[name];
|
|
68
|
+
debug('...' + name);
|
|
69
|
+
nuspecParserChain.push(parseNuspec(dep, targetFramework));
|
|
70
|
+
}
|
|
71
|
+
return Promise.all(nuspecParserChain);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function processNugetInformation(nuspecResolutionChain) {
|
|
75
|
+
const nuspecResolutions = {};
|
|
76
|
+
nuspecResolutionChain.forEach(function (resolution) {
|
|
77
|
+
if (!resolution) {
|
|
78
|
+
return;
|
|
79
|
+
} // jscs:ignore
|
|
80
|
+
debug('.nuspec analyzed for ' + resolution.name);
|
|
81
|
+
nuspecResolutions[resolution.name] = resolution;
|
|
82
|
+
});
|
|
83
|
+
return nuspecResolutions;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
parse: function (tree, manifest, targetFramework, packagesFolder) {
|
|
88
|
+
if (!targetFramework) {
|
|
89
|
+
throw new Error('No valid Dotnet target framework found');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const flattenedPackageList = scanInstalled(manifest, packagesFolder);
|
|
93
|
+
return fetchNugetInformationFromPackages(flattenedPackageList, targetFramework)
|
|
94
|
+
.then(processNugetInformation)
|
|
95
|
+
.then(function buildDependencyTree(nuspecResolutions) {
|
|
96
|
+
// .nuget parsing is complete, returned as array of promise resolutions
|
|
97
|
+
// now the flat list should be rebuilt as a tree
|
|
98
|
+
debug('Building dependency tree');
|
|
99
|
+
function buildTree(node, requiredChildren, repository) {
|
|
100
|
+
requiredChildren.forEach(function (requiredChild) {
|
|
101
|
+
let transitiveDependency;
|
|
102
|
+
if (flattenedPackageList[requiredChild.name]) {
|
|
103
|
+
// fetch from repo
|
|
104
|
+
transitiveDependency =
|
|
105
|
+
flattenedPackageList[requiredChild.name].cloneShallow();
|
|
106
|
+
} else {
|
|
107
|
+
// create as new (uninstalled)
|
|
108
|
+
transitiveDependency = new Dependency(
|
|
109
|
+
requiredChild.name,
|
|
110
|
+
requiredChild.version);
|
|
111
|
+
}
|
|
112
|
+
const transitiveChildren =
|
|
113
|
+
(nuspecResolutions[transitiveDependency.name] &&
|
|
114
|
+
nuspecResolutions[transitiveDependency.name].children) || [];
|
|
115
|
+
buildTree(
|
|
116
|
+
transitiveDependency,
|
|
117
|
+
transitiveChildren,
|
|
118
|
+
repository);
|
|
119
|
+
node.dependencies[transitiveDependency.name] = transitiveDependency;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const _nugtKeyCount = Object.keys(nuspecResolutions).length;
|
|
124
|
+
Object.keys(flattenedPackageList).forEach(function (packageName) {
|
|
125
|
+
tree.dependencies[packageName] =
|
|
126
|
+
flattenedPackageList[packageName].cloneShallow();
|
|
127
|
+
});
|
|
128
|
+
if (_nugtKeyCount > 0) {
|
|
129
|
+
// local folders scanned, build list from .nuspec
|
|
130
|
+
for (const key in nuspecResolutions) {
|
|
131
|
+
const resolution = nuspecResolutions[key];
|
|
132
|
+
const node = flattenedPackageList[resolution.name].cloneShallow();
|
|
133
|
+
buildTree(node, resolution.children, flattenedPackageList);
|
|
134
|
+
tree.dependencies[node.name] = node;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return tree;
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const debug = require('debug')('snyk');
|
|
5
|
+
const getTargetFrameworkFromProjFile = require('./csproj-parser');
|
|
6
|
+
const _ = require('lodash');
|
|
7
|
+
|
|
8
|
+
const dotnetCoreParser = require('./dotnet-core-parser');
|
|
9
|
+
const dotnetFrameworkParser = require('./dotnet-framework-parser');
|
|
10
|
+
const projectJsonParser = require('./project-json-parser');
|
|
11
|
+
const packagesConfigParser = require('./packages-config-parser');
|
|
12
|
+
|
|
13
|
+
const PARSERS = {
|
|
14
|
+
'dotnet-core': {
|
|
15
|
+
depParser: dotnetCoreParser,
|
|
16
|
+
fileContentParser: JSON,
|
|
17
|
+
},
|
|
18
|
+
'project.json': {
|
|
19
|
+
depParser: dotnetFrameworkParser,
|
|
20
|
+
fileContentParser: projectJsonParser,
|
|
21
|
+
},
|
|
22
|
+
'packages.config': {
|
|
23
|
+
depParser: dotnetFrameworkParser,
|
|
24
|
+
fileContentParser: packagesConfigParser,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function getPackagesFolder(packagesFolder, projectRootFolder) {
|
|
29
|
+
if (packagesFolder) {
|
|
30
|
+
return path.resolve(process.cwd(), packagesFolder);
|
|
31
|
+
}
|
|
32
|
+
return path.resolve(projectRootFolder, 'packages');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
buildDepTreeFromFiles: function (root, targetFile, packagesFolderPath, manifestType, useProjectNameFromAssetsFile) {
|
|
37
|
+
const fileContentPath = path.resolve(root || '.', targetFile || '.');
|
|
38
|
+
let fileContent;
|
|
39
|
+
try {
|
|
40
|
+
fileContent = fs.readFileSync(fileContentPath).toString();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return Promise.reject(error);
|
|
43
|
+
}
|
|
44
|
+
const projectRootFolder = path.resolve(fileContentPath, '../../');
|
|
45
|
+
const packagesFolder = getPackagesFolder(packagesFolderPath, projectRootFolder);
|
|
46
|
+
|
|
47
|
+
const tree = {
|
|
48
|
+
name: path.basename(root || projectRootFolder),
|
|
49
|
+
version: '0.0.0',
|
|
50
|
+
packageFormatVersion: 'nuget:0.0.0',
|
|
51
|
+
dependencies: {},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
let targetFramework;
|
|
55
|
+
try {
|
|
56
|
+
if (manifestType === 'dotnet-core') {
|
|
57
|
+
targetFramework = getTargetFrameworkFromProjFile(projectRootFolder);
|
|
58
|
+
} else {
|
|
59
|
+
// .csproj is in the same directory as packages.config or project.json
|
|
60
|
+
targetFramework = getTargetFrameworkFromProjFile(path.resolve(fileContentPath, '../'));
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
return Promise.reject(error);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
tree.meta = {
|
|
67
|
+
targetFramework: targetFramework ? targetFramework.original : undefined, //TODO implement for more than one TF
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const parser = PARSERS[manifestType];
|
|
71
|
+
let manifest = parser.fileContentParser.parse(fileContent, tree);
|
|
72
|
+
|
|
73
|
+
if (manifestType === 'dotnet-core' && useProjectNameFromAssetsFile) {
|
|
74
|
+
let projectName = _.get(manifest, 'project.restore.projectName');
|
|
75
|
+
if (projectName) {
|
|
76
|
+
tree.name = projectName;
|
|
77
|
+
} else {
|
|
78
|
+
debug("project.assets.json file doesn't contain a value for 'projectName'. Using default value: " + tree.name);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return parser.depParser.parse(
|
|
83
|
+
tree,
|
|
84
|
+
manifest,
|
|
85
|
+
targetFramework,
|
|
86
|
+
packagesFolder);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
const JSZip = require('jszip');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const parseXML = require('xml2js').parseString;
|
|
6
|
+
const Dependency = require('./dependency');
|
|
7
|
+
const _ = require('lodash');
|
|
8
|
+
const debug = require('debug')('snyk');
|
|
8
9
|
|
|
9
10
|
const targetFrameworkRegex = /([.a-zA-Z]+)([.0-9]+)/;
|
|
10
11
|
|
|
11
|
-
function parseNuspec(dep,
|
|
12
|
+
function parseNuspec(dep, targetFramework, sep) {
|
|
12
13
|
return Promise.resolve()
|
|
13
14
|
.then(function () {
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const pathSep = sep || '.';
|
|
16
|
+
const nupkgPath =
|
|
16
17
|
path.resolve(dep.path, dep.name + pathSep + dep.version + '.nupkg');
|
|
17
|
-
|
|
18
|
+
const nupkgData = fs.readFileSync(nupkgPath);
|
|
18
19
|
return JSZip.loadAsync(nupkgData);
|
|
19
20
|
})
|
|
20
21
|
.then(function (nuspecZipData) {
|
|
21
|
-
|
|
22
|
+
const nuspecFile = Object.keys(nuspecZipData.files).find(function (file) {
|
|
22
23
|
return (path.extname(file) === '.nuspec');
|
|
23
24
|
});
|
|
24
25
|
return nuspecZipData.files[nuspecFile].async('string');
|
|
@@ -30,7 +31,7 @@ function parseNuspec(dep, targetFrameworks, sep) {
|
|
|
30
31
|
return reject(err);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
let ownDeps = [];
|
|
34
35
|
// We are only going to check the first targetFramework we encounter
|
|
35
36
|
// in the future we may want to support multiple, but only once
|
|
36
37
|
// we have dependency version conflict resolution implemented
|
|
@@ -40,7 +41,7 @@ function parseNuspec(dep, targetFrameworks, sep) {
|
|
|
40
41
|
|
|
41
42
|
// Find and add target framework version specific dependencies
|
|
42
43
|
const depsForTargetFramework =
|
|
43
|
-
|
|
44
|
+
extractDepsForTargetFramework(rawDependency, targetFramework);
|
|
44
45
|
|
|
45
46
|
if (depsForTargetFramework && depsForTargetFramework.group) {
|
|
46
47
|
ownDeps = _.concat(ownDeps,
|
|
@@ -87,7 +88,7 @@ function extractDepsForPlainGroups(rawDependency) {
|
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
function
|
|
91
|
+
function extractDepsForTargetFramework(rawDependency, targetFramework) {
|
|
91
92
|
return rawDependency && _(rawDependency.group)
|
|
92
93
|
.filter(function (group) {
|
|
93
94
|
return group && group.$ && group.$.targetFramework &&
|
|
@@ -103,16 +104,16 @@ function extractDepsForTargetFrameworks(rawDependency, targetFrameworks) {
|
|
|
103
104
|
})
|
|
104
105
|
.orderBy(['framework', 'version'], ['asc', 'desc'])
|
|
105
106
|
.find(function (group) {
|
|
106
|
-
return
|
|
107
|
-
|
|
107
|
+
return targetFramework.framework === group.framework &&
|
|
108
|
+
targetFramework.version >= group.version;
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
function extractDepsFromRaw(rawDependencies) {
|
|
112
|
-
|
|
113
|
+
const deps = [];
|
|
113
114
|
_.forEach(rawDependencies, function (dependency) {
|
|
114
115
|
if (dependency && dependency.$) {
|
|
115
|
-
|
|
116
|
+
const dep = new Dependency(dependency.$.id, dependency.$.version);
|
|
116
117
|
deps.push(dep);
|
|
117
118
|
}
|
|
118
119
|
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const parseXML = require('xml2js').parseString;
|
|
3
|
+
const debug = require('debug')('snyk');
|
|
4
|
+
const Dependency = require('./dependency');
|
|
5
|
+
|
|
6
|
+
function parsePackagesConfigFileContents(fileContent) {
|
|
7
|
+
const installedPackages = [];
|
|
8
|
+
debug('Trying to parse packages.config manifest');
|
|
9
|
+
parseXML(fileContent, function (err, result) {
|
|
10
|
+
if (err) {
|
|
11
|
+
throw err;
|
|
12
|
+
} else {
|
|
13
|
+
const packages = result.packages.package || [];
|
|
14
|
+
|
|
15
|
+
packages.forEach(
|
|
16
|
+
function scanPackagesConfigNode(node) {
|
|
17
|
+
const installedDependency =
|
|
18
|
+
Dependency.from.packgesConfigEntry(node);
|
|
19
|
+
installedPackages.push(installedDependency);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return installedPackages;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
parse: parsePackagesConfigFileContents,
|
|
28
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const debug = require('debug')('snyk');
|
|
3
|
+
const Dependency = require('./dependency');
|
|
4
|
+
|
|
5
|
+
function scanForDependencies(obj, deps) {
|
|
6
|
+
deps = deps || {};
|
|
7
|
+
if (typeof obj !== 'object') {
|
|
8
|
+
return deps;
|
|
9
|
+
}
|
|
10
|
+
Object.keys(obj).forEach(function (key) {
|
|
11
|
+
if (key === 'dependencies') {
|
|
12
|
+
const dependencies = obj.dependencies;
|
|
13
|
+
Object.keys(dependencies).forEach(function (key) {
|
|
14
|
+
const depName = key;
|
|
15
|
+
let version = dependencies[key];
|
|
16
|
+
if (typeof version === 'object') {
|
|
17
|
+
version = version.version;
|
|
18
|
+
}
|
|
19
|
+
if (typeof version === 'undefined') {
|
|
20
|
+
version = 'unknown';
|
|
21
|
+
} else {
|
|
22
|
+
version = version.toString();
|
|
23
|
+
}
|
|
24
|
+
deps[depName] = version;
|
|
25
|
+
});
|
|
26
|
+
} else {
|
|
27
|
+
scanForDependencies(obj[key], deps);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
return deps;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseJsonManifest(fileContent) {
|
|
34
|
+
const rawContent = JSON.parse(fileContent);
|
|
35
|
+
const result = {};
|
|
36
|
+
result.dependencies = scanForDependencies(rawContent, {});
|
|
37
|
+
if (typeof rawContent.project === 'object') {
|
|
38
|
+
const pData = rawContent.project;
|
|
39
|
+
const name = (pData.restore && pData.restore.projectName);
|
|
40
|
+
result.project = {
|
|
41
|
+
version: pData.version || '0.0.0',
|
|
42
|
+
};
|
|
43
|
+
if (name) {
|
|
44
|
+
result.project.name = name;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function parseProjectJsonFileContents(fileContent, tree) {
|
|
51
|
+
const installedPackages = [];
|
|
52
|
+
debug('Trying to parse project.json format manifest');
|
|
53
|
+
const projectData = parseJsonManifest(fileContent);
|
|
54
|
+
const rawDependencies = projectData.dependencies;
|
|
55
|
+
debug(rawDependencies);
|
|
56
|
+
if (rawDependencies) {
|
|
57
|
+
for (const name in rawDependencies) {
|
|
58
|
+
// Array<{ "libraryName": "version" }>
|
|
59
|
+
const version = rawDependencies[name];
|
|
60
|
+
const newDependency = new Dependency(name, version, null);
|
|
61
|
+
installedPackages.push(newDependency);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (projectData.project) {
|
|
65
|
+
tree.name = projectData.project.name;
|
|
66
|
+
tree.version = projectData.project.version;
|
|
67
|
+
}
|
|
68
|
+
return installedPackages;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
parse: parseProjectJsonFileContents,
|
|
73
|
+
};
|
package/package.json
CHANGED
package/lib/dotnet-parser.js
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
var fs = require('fs');
|
|
2
|
-
var parseXML = require('xml2js').parseString;
|
|
3
|
-
var Dependency = require('./dependency');
|
|
4
|
-
var path = require('path');
|
|
5
|
-
var parseNuspec = require('./nuspec-parser');
|
|
6
|
-
var jsonManifestParser = require('./json-manifest-parser');
|
|
7
|
-
var debug = require('debug')('snyk');
|
|
8
|
-
var projectJsonFormatParser = require('./formats/dotnet-core-parser');
|
|
9
|
-
var determineDotnetVersions = require('./proj-parser');
|
|
10
|
-
|
|
11
|
-
function injectProjectData(tree, projectData) {
|
|
12
|
-
tree.name = projectData.project.name;
|
|
13
|
-
tree.version = projectData.project.version;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function injectPath(dep, packagesFolder) {
|
|
17
|
-
dep.path =
|
|
18
|
-
dep.localPath ?
|
|
19
|
-
path.resolve(packagesFolder, dep.localPath)
|
|
20
|
-
: path.resolve(packagesFolder, dep.name + '.' + dep.version);
|
|
21
|
-
if (dep.localPath) {
|
|
22
|
-
delete dep.localPath;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function getPackagesFolder(packagesFolder, projectRootFolder) {
|
|
27
|
-
if (packagesFolder) {
|
|
28
|
-
return path.resolve(process.cwd(), packagesFolder);
|
|
29
|
-
}
|
|
30
|
-
return path.resolve(projectRootFolder, 'packages');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
module.exports = {
|
|
34
|
-
parse: function (root, targetFile, packagesFolder, fileContentPath, manifestType) {
|
|
35
|
-
var fileContent;
|
|
36
|
-
try {
|
|
37
|
-
fileContent = fs.readFileSync(fileContentPath).toString();
|
|
38
|
-
} catch (error) {
|
|
39
|
-
return Promise.reject(error);
|
|
40
|
-
}
|
|
41
|
-
var projectRootFolder = path.resolve(fileContentPath, '../../');
|
|
42
|
-
var packagesFolder = getPackagesFolder(packagesFolder, projectRootFolder);
|
|
43
|
-
var dotnetVersions;
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
if (manifestType === 'dotnet-core') {
|
|
47
|
-
dotnetVersions = determineDotnetVersions(projectRootFolder);
|
|
48
|
-
} else {
|
|
49
|
-
// .csproj is in the same directory as packages.config or project.json
|
|
50
|
-
dotnetVersions = determineDotnetVersions(path.resolve(fileContentPath, '../'));
|
|
51
|
-
}
|
|
52
|
-
} catch (error) {
|
|
53
|
-
return Promise.reject(error);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
debug('Loaded ' + targetFile + ' with manifest type '
|
|
57
|
-
+ manifestType + ' for .NET version ' + dotnetVersions);
|
|
58
|
-
|
|
59
|
-
var flattendPackageList = {};
|
|
60
|
-
var nuspecResolutions = {};
|
|
61
|
-
|
|
62
|
-
var tree = {
|
|
63
|
-
name: path.basename(root || projectRootFolder),
|
|
64
|
-
version: '0.0.0',
|
|
65
|
-
packageFormatVersion: 'nuget:0.0.0',
|
|
66
|
-
dependencies: {},
|
|
67
|
-
meta: {
|
|
68
|
-
targetFramework: dotnetVersions[0].original, //TODO implement for more than one TF
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
return new Promise(function parseFileContents(resolve, reject) {
|
|
73
|
-
var installedPackages = [];
|
|
74
|
-
switch (manifestType) {
|
|
75
|
-
case 'dotnet-core': {
|
|
76
|
-
debug('Trying to parse dot-net-cli manifest');
|
|
77
|
-
projectJsonFormatParser(fileContent, tree);
|
|
78
|
-
resolve([]); // skip installed dependencies parsing
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
case 'project.json': {
|
|
82
|
-
debug('Trying to parse project.json format manifest');
|
|
83
|
-
var projectData = jsonManifestParser.parse(fileContent);
|
|
84
|
-
var rawDependencies = projectData.dependencies;
|
|
85
|
-
debug(rawDependencies);
|
|
86
|
-
if (rawDependencies) {
|
|
87
|
-
for (var name in rawDependencies) {
|
|
88
|
-
// Array<{ "libraryName": "version" }>
|
|
89
|
-
var version = rawDependencies[name];
|
|
90
|
-
var newDependency = new Dependency(name, version, null);
|
|
91
|
-
installedPackages.push(newDependency);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (projectData.project) {
|
|
95
|
-
injectProjectData(tree, projectData);
|
|
96
|
-
}
|
|
97
|
-
resolve(installedPackages);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
case 'packages.config': {
|
|
101
|
-
debug('Trying to parse packages.config manifest');
|
|
102
|
-
parseXML(fileContent, function scanPackagesConfig(err, result) {
|
|
103
|
-
if (err) {
|
|
104
|
-
reject(err);
|
|
105
|
-
} else {
|
|
106
|
-
result.packages.package.forEach(
|
|
107
|
-
function scanPackagesConfigNode(node) {
|
|
108
|
-
var installedDependency =
|
|
109
|
-
Dependency.from.packgesConfigEntry(node);
|
|
110
|
-
installedPackages.push(installedDependency);
|
|
111
|
-
});
|
|
112
|
-
resolve(installedPackages);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}).then(function scanInstalled(installedPackages) {
|
|
119
|
-
if (manifestType !== 'dotnet-core') {
|
|
120
|
-
debug('Located ' + installedPackages.length + ' packages in manifest');
|
|
121
|
-
installedPackages.forEach(function (entry) {
|
|
122
|
-
injectPath(entry, packagesFolder);
|
|
123
|
-
flattendPackageList[entry.name] =
|
|
124
|
-
flattendPackageList[entry.name] || entry;
|
|
125
|
-
debug('Entry: ' + entry.name + ' -> ' + entry.path);
|
|
126
|
-
});
|
|
127
|
-
try {
|
|
128
|
-
debug('Scanning local installed folders');
|
|
129
|
-
debug('Trying to read from installed packages folder: ' +
|
|
130
|
-
packagesFolder);
|
|
131
|
-
fs.readdirSync(packagesFolder)
|
|
132
|
-
.map(function (folderName) {
|
|
133
|
-
return Dependency.from.folderName(folderName);
|
|
134
|
-
})
|
|
135
|
-
.forEach(function (dep) {
|
|
136
|
-
injectPath(dep, packagesFolder);
|
|
137
|
-
// only add a package from packages folder if version is different
|
|
138
|
-
if (flattendPackageList[dep.name] &&
|
|
139
|
-
flattendPackageList[dep.name].version !== dep.version) {
|
|
140
|
-
// prefer found from packages folder (dep) over existing
|
|
141
|
-
debug('For package ' + dep.name + ' the version ' +
|
|
142
|
-
flattendPackageList[dep.name].version +
|
|
143
|
-
' was extracted from manifest file.' +
|
|
144
|
-
'\nWe are overwriting it with version ' + dep.version +
|
|
145
|
-
' from the packages folder');
|
|
146
|
-
flattendPackageList[dep.name] = dep;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
} catch (err) {
|
|
150
|
-
debug('Could not complete packages folder scanning');
|
|
151
|
-
debug(err);
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
debug('Located ' +
|
|
155
|
-
Object.keys(tree.dependencies).length + 'packages in manifest');
|
|
156
|
-
var sorted = {};
|
|
157
|
-
Object.keys(flattendPackageList).sort().forEach(function (key) {
|
|
158
|
-
sorted[key] = flattendPackageList[key];
|
|
159
|
-
});
|
|
160
|
-
flattendPackageList = sorted;
|
|
161
|
-
}
|
|
162
|
-
}).then(function fetchNugetInformationFromPackages() {
|
|
163
|
-
var nuspecParserChain = [];
|
|
164
|
-
if (manifestType !== 'dotnet-core') {
|
|
165
|
-
// begin collecting information from .nuget files on installed packages
|
|
166
|
-
debug('Trying to analyze .nuspec files');
|
|
167
|
-
for (var name in flattendPackageList) {
|
|
168
|
-
var dep = flattendPackageList[name];
|
|
169
|
-
debug('...' + name);
|
|
170
|
-
nuspecParserChain.push(parseNuspec(dep, dotnetVersions));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return Promise.all(nuspecParserChain);
|
|
174
|
-
}).then(function processNugetInformation(nuspecResolutionChain) {
|
|
175
|
-
if (manifestType !== 'dotnet-core') {
|
|
176
|
-
nuspecResolutionChain.forEach(function (resolution) {
|
|
177
|
-
if (!resolution) {
|
|
178
|
-
return;
|
|
179
|
-
} // jscs:ignore
|
|
180
|
-
debug('.nuspec analyzed for ' + resolution.name);
|
|
181
|
-
nuspecResolutions[resolution.name] = resolution;
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
}).then(function buildDependencyTree() {
|
|
185
|
-
// .nuget parsing is complete, returned as array of promise resolutions
|
|
186
|
-
// now the flat list should be rebuilt as a tree
|
|
187
|
-
debug('Building dependency tree');
|
|
188
|
-
function buildTree(node, requiredChildren, repository) {
|
|
189
|
-
requiredChildren.forEach(function (requiredChild) {
|
|
190
|
-
var transitiveDependency;
|
|
191
|
-
if (flattendPackageList[requiredChild.name]) {
|
|
192
|
-
// fetch from repo
|
|
193
|
-
transitiveDependency =
|
|
194
|
-
flattendPackageList[requiredChild.name].cloneShallow();
|
|
195
|
-
} else {
|
|
196
|
-
// create as new (uninstalled)
|
|
197
|
-
transitiveDependency = new Dependency(
|
|
198
|
-
requiredChild.name,
|
|
199
|
-
requiredChild.version);
|
|
200
|
-
}
|
|
201
|
-
var transitiveChildren =
|
|
202
|
-
(nuspecResolutions[transitiveDependency.name] &&
|
|
203
|
-
nuspecResolutions[transitiveDependency.name].children) || [];
|
|
204
|
-
buildTree(
|
|
205
|
-
transitiveDependency,
|
|
206
|
-
transitiveChildren,
|
|
207
|
-
repository);
|
|
208
|
-
node.dependencies[transitiveDependency.name] = transitiveDependency;
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
var _nugtKeyCount = Object.keys(nuspecResolutions).length;
|
|
213
|
-
Object.keys(flattendPackageList).forEach(function (packageName) {
|
|
214
|
-
tree.dependencies[packageName] =
|
|
215
|
-
flattendPackageList[packageName].cloneShallow();
|
|
216
|
-
});
|
|
217
|
-
if (_nugtKeyCount > 0) {
|
|
218
|
-
// local folders scanned, build list from .nuspec
|
|
219
|
-
for (var key in nuspecResolutions) {
|
|
220
|
-
var resolution = nuspecResolutions[key];
|
|
221
|
-
var node = flattendPackageList[resolution.name].cloneShallow();
|
|
222
|
-
buildTree(node, resolution.children, flattendPackageList);
|
|
223
|
-
tree.dependencies[node.name] = node;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return tree;
|
|
227
|
-
})['catch'](function (err) {
|
|
228
|
-
throw (err);
|
|
229
|
-
});
|
|
230
|
-
},
|
|
231
|
-
};
|
package/lib/find-folder.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
var path = require('path');
|
|
2
|
-
var fs = require('fs');
|
|
3
|
-
|
|
4
|
-
function findFolder(dir) {
|
|
5
|
-
var parts = dir.split(path.sep);
|
|
6
|
-
var testPath;
|
|
7
|
-
while (parts.length > 0) {
|
|
8
|
-
testPath = path.join(parts.join(path.sep), 'packages');
|
|
9
|
-
if (fs.existsSync(testPath)) {
|
|
10
|
-
return testPath;
|
|
11
|
-
}
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = findFolder;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
function scanForDependencies(obj, deps) {
|
|
2
|
-
deps = deps || {};
|
|
3
|
-
if (typeof obj !== 'object') {
|
|
4
|
-
return deps;
|
|
5
|
-
}
|
|
6
|
-
Object.keys(obj).forEach(function (key) {
|
|
7
|
-
if (key === 'dependencies') {
|
|
8
|
-
var dependencies = obj.dependencies;
|
|
9
|
-
Object.keys(dependencies).forEach(function (key) {
|
|
10
|
-
var depName = key;
|
|
11
|
-
var version = dependencies[key];
|
|
12
|
-
if (typeof version === 'object') {
|
|
13
|
-
version = version.version;
|
|
14
|
-
}
|
|
15
|
-
if (typeof version === 'undefined') {
|
|
16
|
-
version = 'unknown';
|
|
17
|
-
} else {
|
|
18
|
-
version = version.toString();
|
|
19
|
-
}
|
|
20
|
-
deps[depName] = version;
|
|
21
|
-
});
|
|
22
|
-
} else {
|
|
23
|
-
scanForDependencies(obj[key], deps);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
return deps;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module.exports = {
|
|
30
|
-
parse: function parseJsonManifest(fileContent) {
|
|
31
|
-
var rawContent = JSON.parse(fileContent);
|
|
32
|
-
var result = {};
|
|
33
|
-
result.dependencies = scanForDependencies(rawContent, {});
|
|
34
|
-
if (typeof rawContent.project === 'object') {
|
|
35
|
-
var pData = rawContent.project;
|
|
36
|
-
var name = (pData.restore && pData.restore.projectName);
|
|
37
|
-
result.project = {
|
|
38
|
-
version: pData.version || '0.0.0',
|
|
39
|
-
};
|
|
40
|
-
if (name) {
|
|
41
|
-
result.project.name = name;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return result;
|
|
45
|
-
},
|
|
46
|
-
};
|
package/lib/proj-parser.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const parseXML = require('xml2js').parseString;
|
|
4
|
-
const debug = require('debug')('snyk');
|
|
5
|
-
const _ = require('lodash');
|
|
6
|
-
|
|
7
|
-
function determineDotnetVersions(rootDir) {
|
|
8
|
-
debug('Looking for your .csproj file in ' + rootDir);
|
|
9
|
-
const csprojPath = findFile(rootDir, /.*\.csproj$/);
|
|
10
|
-
if (!csprojPath) {
|
|
11
|
-
throw new Error('.csproj file not found in ' + rootDir + '. ' +
|
|
12
|
-
'Make sure project was built before running `snyk test`');
|
|
13
|
-
}
|
|
14
|
-
debug('Checking .net framework version in .csproj file ' + csprojPath);
|
|
15
|
-
|
|
16
|
-
const csprojContents = fs.readFileSync(csprojPath);
|
|
17
|
-
|
|
18
|
-
var frameworks = [];
|
|
19
|
-
parseXML(csprojContents, function (err, parsedCsprojContents) {
|
|
20
|
-
if (err) {
|
|
21
|
-
throw err;
|
|
22
|
-
}
|
|
23
|
-
const versionLoc = _.get(parsedCsprojContents, 'Project.PropertyGroup[0]');
|
|
24
|
-
const versions = _.compact(_.concat([],
|
|
25
|
-
_.get(versionLoc, 'TargetFrameworkVersion[0]') ||
|
|
26
|
-
_.get(versionLoc, 'TargetFramework[0]') ||
|
|
27
|
-
_.get(versionLoc, 'TargetFrameworks[0]', '').split(';')));
|
|
28
|
-
|
|
29
|
-
if (versions.length < 1) {
|
|
30
|
-
throw new Error('Could not find TargetFrameworkVersion/TargetFramework' +
|
|
31
|
-
'/TargetFrameworks defined in the Project.PropertyGroup field of ' +
|
|
32
|
-
'your .csproj file');
|
|
33
|
-
}
|
|
34
|
-
frameworks = _.compact(_.map(versions, toReadableFramework));
|
|
35
|
-
});
|
|
36
|
-
if (frameworks.length < 1) {
|
|
37
|
-
throw new Error('Could not find valid/supported .NET version');
|
|
38
|
-
}
|
|
39
|
-
return frameworks;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function toReadableFramework(targetFramework) {
|
|
43
|
-
const typeMapping = {
|
|
44
|
-
v: '.NETFramework',
|
|
45
|
-
net: '.NETFramework',
|
|
46
|
-
netstandard: '.NETStandard',
|
|
47
|
-
netcoreapp: '.NETCore',
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
for (var type in typeMapping) {
|
|
51
|
-
if (new RegExp(type + /\d.?\d(.?\d)?$/.source).test(targetFramework)) {
|
|
52
|
-
return {
|
|
53
|
-
framework: typeMapping[type],
|
|
54
|
-
version: targetFramework.split(type)[1],
|
|
55
|
-
original: targetFramework,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function findFile(rootDir, filter) {
|
|
62
|
-
if (!fs.existsSync(rootDir)) {
|
|
63
|
-
throw new Error('No such path: ' + rootDir);
|
|
64
|
-
}
|
|
65
|
-
const files = fs.readdirSync(rootDir);
|
|
66
|
-
for (var i = 0; i < files.length; i++) {
|
|
67
|
-
var filename = path.resolve(rootDir, files[i]);
|
|
68
|
-
|
|
69
|
-
if (filter.test(filename)) {
|
|
70
|
-
return filename;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = determineDotnetVersions;
|