summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/npm-audit-report/reporters/parseable.js
blob: 363359772916c377605c802cd2ea71d9ca94c5a1 (plain)
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
'use strict'

const report = function (data, options) {
  const defaults = {
    severityThreshold: 'info'
  }

  const config = Object.assign({}, defaults, options)

  let exit = 0

  const actions = function (data, config) {
    let accumulator = {
      high: '',
      moderate: '',
      low: ''
    }

    if (Object.keys(data.advisories).length !== 0) {
      data.actions.forEach((action) => {
        let l = {}
        // Start with install/update actions
        if (action.action === 'update' || action.action === 'install') {
          const recommendation = getRecommendation(action, config)
          l.recommendation = recommendation.cmd
          l.breaking = recommendation.isBreaking ? 'Y' : 'N'

          // TODO: Verify: The advisory seems to repeat and be the same for all the 'resolves'. Is it true?
          const advisory = data.advisories[action.resolves[0].id]
          l.sevLevel = advisory.severity
          l.severity = advisory.title
          l.package = advisory.module_name
          l.moreInfo = `https://nodesecurity.io/advisories/${advisory.id}`
          l.path = action.resolves[0].path

          accumulator[advisory.severity] += [action.action, l.package, l.sevLevel, l.recommendation, l.severity, l.moreInfo, l.path, l.breaking]
            .join('\t') + '\n'
        }

        if (action.action === 'review') {
          action.resolves.forEach((resolution) => {
            const advisory = data.advisories[resolution.id]

            l.sevLevel = advisory.severity
            l.severity = advisory.title
            l.package = advisory.module_name
            l.moreInfo = `https://nodesecurity.io/advisories/${advisory.id}`
            l.patchedIn = advisory.patched_versions.replace(' ', '') === '<0.0.0' ? 'No patch available' : advisory.patched_versions
            l.path = resolution.path

            accumulator[advisory.severity] += [action.action, l.package, l.sevLevel, l.patchedIn, l.severity, l.moreInfo, l.path].join('\t') + '\n'
          }) // forEach resolves
        } // is review
      }) // forEach actions
    }
    return accumulator['high'] + accumulator['moderate'] + accumulator['low']
  }

  const exitCode = function (metadata) {
    let total = 0
    const keys = Object.keys(metadata.vulnerabilities)
    for (let key of keys) {
      const value = metadata.vulnerabilities[key]
      total = total + value
    }

    if (total > 0) {
      exit = 1
    }
  }

  exitCode(data.metadata)

  return {
    report: actions(data, config),
    exitCode: exit
  }
}

const getRecommendation = function (action, config) {
  if (action.action === 'install') {
    const isDev = action.resolves[0].dev

    return {
      cmd: `npm install ${isDev ? '--save-dev ' : ''}${action.module}@${action.target}`,
      isBreaking: action.isMajor
    }
  } else {
    return {
      cmd: `npm update ${action.module} --depth ${action.depth}`,
      isBreaking: false
    }
  }
}

module.exports = report