-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
151 lines (123 loc) · 3.78 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const _ = require("lodash")
const fs = require("fs")
const vile = require("vile")
const Bluebird = require("bluebird")
const RETIRE_BIN = "retire"
const RETIRE_REPORT = "retire-report.json"
Bluebird.promisifyAll(fs)
let to_json = (string) =>
_.attempt(JSON.parse.bind(null, string))
let remove_report = () =>
fs.unlinkAsync(RETIRE_REPORT)
let read_report = () =>
fs.readFileAsync(RETIRE_REPORT)
.then((data) =>
remove_report().then(() =>
data ? to_json(data) : []))
let retire_check = (plugin_config) => {
let cli_opts = _.get(plugin_config, "config", {})
let cli_opts_as_args = _.flatMap(cli_opts, (value, name) => {
let opt = [ `--${name}` ]
if (_.isArray(value)) value = value.join(",")
if (_.isString(value)) opt.push(value)
return opt
})
let opts = {
args: _.concat(
cli_opts_as_args,
[
"--outputformat",
"json",
"--outputpath",
RETIRE_REPORT
])
}
return vile
.spawn(RETIRE_BIN, opts)
.then(read_report)
}
let result_name = (result) =>
_.get(result, "component")
let result_version = (result) =>
_.get(result, "version")
let sec_path = (vulnerability, result) =>
_.has(result, "file") ? _.get(result, "file") : "package.json"
let description = (vulnerability) =>
_.get(vulnerability, "identifiers.advisory",
_.get(vulnerability, "identifiers.summary",
"has known security vulnerabilities"))
let cve = (vulnerability) =>
_.get(vulnerability, "identifiers.CVE")
let vile_issue = (vulnerability, result, file) => {
let severity = _.get(vulnerability, "severity")
let desc = description(vulnerability)
let name = result_name(result)
let id = cve(vulnerability)
let version = result_version(result)
// TODO: ideally, we can pass all links
let advisories = _.get(vulnerability, "info", [])
let advisory = _.first(advisories)
let msg = ""
if (name) msg += `(${name}@${version})`
if (id) msg += ` ${id}`
msg += ` ${desc}`
if (severity) msg += ` (severity: ${severity})`
if (!_.isEmpty(advisories) && advisories.length > 1) {
msg += ` \n\n${_.slice(advisories, 1).join("\n\n")}`
}
let sig_postfix = id || advisory || desc
let sig = `retire::${name}::${version}::${sig_postfix}`
let sec_info = {
package: name,
version: version,
advisory: advisory
}
return vile.issue({
type: vile.SEC,
path: sec_path(vulnerability, result),
message: _.trim(msg),
signature: sig,
security: sec_info
})
}
// TODO: this needs some TLC/refactoring, etc
let into_issues = (reports) => {
let issues = []
// HACK: to make manipulation a lot easier
_.each(reports, (report) => {
if (_.has(report, "file")) {
_.each(_.get(report, "results"), (result) => {
_.set(result, "file", _.get(report, "file"))
})
}
})
let results = _.flatMap(reports, "results")
// [name][ver] = [ result, ... ]
let map_by_name = _.reduce(results, (map, result) => {
let name = _.get(result, "component", "?")
let ver = _.get(result, "version", "?")
if (!map[name]) map[name] = {}
if (!map[name][ver]) map[name][ver] = []
map[name][ver].push(result)
return map
}, {})
_.each(map_by_name, (versions, name) => {
_.each(versions, (results, version) => {
_.each(results, (result) => {
let file = _.get(result, "file")
let vulnerabilities = _.get(result, "vulnerabilities", [])
_.each(vulnerabilities, (vulnerability) => {
issues.push(vile_issue(vulnerability, result, file))
})
})
})
})
// HACK: noticed odd dupe data with retire cli? this ensures no true dupes
return _.uniqBy(issues, (issue) => issue.message + issue.signature)
}
let punish = (plugin_data) =>
retire_check(plugin_data)
.then(into_issues)
module.exports = {
punish: punish
}