UNPKG

4.15 kBJavaScriptView Raw
1/*jshint esversion: 6 */
2var retire = require('./retire'),
3 fs = require('fs'),
4 crypto = require('crypto'),
5 path = require('path'),
6 utils = require('./utils'),
7 emitter = new require('events').EventEmitter;
8
9var events = new emitter();
10
11var hash = {
12 'sha1' : function(data) {
13 shasum = crypto.createHash('sha1');
14 shasum.update(data);
15 return shasum.digest('hex');
16 }
17};
18
19function emitResults(finding, options) {
20 removeIgnored(finding.results, options.ignore);
21 if (!options.verbose) finding.results = finding.results.filter(f => retire.isVulnerable([f]));
22 if (finding.results.length == 0) return;
23 if (retire.isVulnerable(finding.results)) {
24 events.emit('vulnerable-dependency-found', finding);
25 } else {
26 events.emit('dependency-found', finding);
27 }
28
29}
30
31function shouldIgnorePath(fileSpecs, ignores) {
32 return utils.detect(ignores.paths, function(i) {
33 return utils.detect(fileSpecs, function(j) {
34 return i.test(j) || i.test(path.resolve(j));
35 });
36 });
37}
38
39function removeIgnored(results, ignores) {
40 if (!ignores.hasOwnProperty('descriptors')) return;
41 results.forEach(function(r) {
42 if (!r.hasOwnProperty('vulnerabilities')) return;
43 ignores.descriptors.forEach(function(i) {
44 if (r.component !== i.component) return;
45 if (i.version && r.version !== i.version) return;
46 if (i.severity && r.severity !== i.severity) return;
47 if (i.identifiers) {
48 removeIgnoredVulnerabilitiesByIdentifier(i.identifiers, r);
49 return;
50 }
51 r.vulnerabilities = [];
52 });
53 if (r.vulnerabilities.length === 0) delete r.vulnerabilities;
54 });
55}
56
57function removeIgnoredVulnerabilitiesByIdentifier(identifiers, result) {
58 result.vulnerabilities = result.vulnerabilities.filter(function(v) {
59 if (!v.hasOwnProperty("identifiers")) return true;
60 return !utils.every(identifiers, function(key, value) { return hasIdentifier(v, key, value); });
61 });
62}
63function hasIdentifier(vulnerability, key, value) {
64 if (!vulnerability.identifiers.hasOwnProperty(key)) return false;
65 var identifier = vulnerability.identifiers[key];
66 return Array.isArray(identifier) ? identifier.some(function(x) { return x === value; }) : identifier === value;
67}
68
69
70function scanJsFile(file, repo, options) {
71 if (options.ignore && shouldIgnorePath([file], options.ignore)) {
72 return;
73 }
74 var results = retire.scanFileName(file, repo);
75 if (!results || results.length === 0) {
76 results = retire.scanFileContent(fs.readFileSync(file), repo, hash);
77 }
78 emitResults({file: file, results: results}, options);
79}
80
81
82function scanDependencies(dependencies, nodeRepo, options) {
83 for (var i in dependencies) {
84 var dependency = dependencies[i];
85 var fileSpecs = [toModulePath(dependency)];
86 if (dependency.component) {
87 fileSpecs.push(dependency.component);
88 }
89
90 if (options.ignore && shouldIgnorePath(fileSpecs, options.ignore)) {
91 continue;
92 }
93 results = retire.scanNodeDependency(dependencies[i].module, nodeRepo, options);
94 emitResults({file: dependencies[i].file, results: results}, options);
95 }
96}
97
98function toModulePath(dep) {
99 function f(d) {
100 if (d.parent) return f(d.parent) + '/node_modules/' + d.component;
101 return '';
102 }
103 return path.resolve(f(dep).substring(1));
104}
105
106
107
108function scanBowerFile(file, repo, options) {
109 if (options.ignore && shouldIgnorePath([file], options.ignore)) {
110 return;
111 }
112 try {
113 var bower = JSON.parse(fs.readFileSync(file));
114 if (bower.version) {
115 var results = retire.check(bower.name, bower.version, repo);
116 emitResults({file: file, results: results}, options);
117 }
118 } catch (e) {
119 options.log.warn('Could not parse file: ' + file);
120 }
121}
122
123
124
125exports.scanDependencies = function(dependencies, nodeRepo, options) {
126 return scanDependencies(dependencies, nodeRepo, options);
127};
128exports.scanJsFile = function(file, repo, options) {
129 return scanJsFile(file, repo, options);
130};
131exports.scanBowerFile = function(file, repo, options) {
132 return scanBowerFile(file, repo, options);
133};
134exports.on = function(name, listener) {
135 events.on(name, listener);
136};
137
138