• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const report = function (data, options) {
4  const defaults = {
5    severityThreshold: 'info'
6  }
7
8  const config = Object.assign({}, defaults, options)
9
10  let exit = 0
11
12  const actions = function (data, config) {
13    let accumulator = {
14      critical: '',
15      high: '',
16      moderate: '',
17      low: ''
18    }
19
20    if (Object.keys(data.advisories).length !== 0) {
21      data.actions.forEach((action) => {
22        let l = {}
23        // Start with install/update actions
24        if (action.action === 'update' || action.action === 'install') {
25          const recommendation = getRecommendation(action, config)
26          l.recommendation = recommendation.cmd
27          l.breaking = recommendation.isBreaking ? 'Y' : 'N'
28
29          action.resolves.forEach((resolution) => {
30            const advisory = data.advisories[resolution.id]
31
32            l.sevLevel = advisory.severity
33            l.severity = advisory.title
34            l.package = advisory.module_name
35            l.moreInfo = advisory.url || `https://www.npmjs.com/advisories/${advisory.id}`
36            l.path = resolution.path
37
38            accumulator[advisory.severity] += [action.action, l.package, l.sevLevel, l.recommendation, l.severity, l.moreInfo, l.path, l.breaking]
39              .join('\t') + '\n'
40          }) // forEach resolves
41        }
42
43        if (action.action === 'review') {
44          action.resolves.forEach((resolution) => {
45            const advisory = data.advisories[resolution.id]
46
47            l.sevLevel = advisory.severity
48            l.severity = advisory.title
49            l.package = advisory.module_name
50            l.moreInfo = advisory.url || `https://www.npmjs.com/advisories/${advisory.id}`
51            l.patchedIn = advisory.patched_versions.replace(' ', '') === '<0.0.0' ? 'No patch available' : advisory.patched_versions
52            l.path = resolution.path
53
54            accumulator[advisory.severity] += [action.action, l.package, l.sevLevel, l.patchedIn, l.severity, l.moreInfo, l.path].join('\t') + '\n'
55          }) // forEach resolves
56        } // is review
57      }) // forEach actions
58    }
59    return accumulator['critical'] + accumulator['high'] + accumulator['moderate'] + accumulator['low']
60  }
61
62  const exitCode = function (metadata) {
63    let total = 0
64    const keys = Object.keys(metadata.vulnerabilities)
65    for (let key of keys) {
66      const value = metadata.vulnerabilities[key]
67      total = total + value
68    }
69
70    if (total > 0) {
71      exit = 1
72    }
73  }
74
75  exitCode(data.metadata)
76
77  return {
78    report: actions(data, config),
79    exitCode: exit
80  }
81}
82
83const getRecommendation = function (action, config) {
84  if (action.action === 'install') {
85    const isDev = action.resolves[0].dev
86
87    return {
88      cmd: `npm install ${isDev ? '--save-dev ' : ''}${action.module}@${action.target}`,
89      isBreaking: action.isMajor
90    }
91  } else {
92    return {
93      cmd: `npm update ${action.module} --depth ${action.depth}`,
94      isBreaking: false
95    }
96  }
97}
98
99module.exports = report
100