This commit is contained in:
2025-08-18 23:06:34 +08:00
parent 0bc04fb659
commit ed18af0cad
1926 changed files with 275098 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
'use strict'
const colors = require('../colors.js')
const install = require('./install.js')
module.exports = (data, { chalk }) => {
const summary = install.summary(data, { chalk })
const none = data.metadata.vulnerabilities.total === 0
return none ? summary : fullReport(data, { chalk, summary })
}
const fullReport = (data, { chalk, summary }) => {
const c = colors(chalk)
const output = [c.white('# npm audit report'), '']
const printed = new Set()
for (const [, vuln] of Object.entries(data.vulnerabilities)) {
// only print starting from the top-level advisories
if (vuln.via.filter(v => typeof v !== 'string').length !== 0) {
output.push(printVuln(vuln, c, data.vulnerabilities, printed))
}
}
output.push(summary)
return output.join('\n')
}
const printVuln = (vuln, c, vulnerabilities, printed, indent = '') => {
if (printed.has(vuln)) {
return null
}
printed.add(vuln)
const output = []
output.push(c.white(vuln.name) + ' ' + vuln.range)
if (indent === '' && (vuln.severity !== 'low' || vuln.severity === 'info')) {
output.push(`Severity: ${c.severity(vuln.severity)}`)
}
for (const via of vuln.via) {
if (typeof via === 'string') {
output.push(`Depends on vulnerable versions of ${c.white(via)}`)
} else if (indent === '') {
output.push(`${c.white(via.title)} - ${via.url}`)
}
}
if (indent === '') {
const { fixAvailable: fa } = vuln
if (fa === false) {
output.push(c.red('No fix available'))
} else if (fa === true) {
output.push(c.green('fix available') + ' via `npm audit fix`')
} else {
/* istanbul ignore else - should be impossible, just being cautious */
if (typeof fa === 'object' && indent === '') {
output.push(
`${c.yellow('fix available')} via \`npm audit fix --force\``,
`Will install ${fa.name}@${fa.version}` +
`, which is ${fa.isSemVerMajor ? 'a breaking change' :
'outside the stated dependency range'}`
)
}
}
}
for (const path of vuln.nodes) {
output.push(c.dim(path))
}
for (const effect of vuln.effects) {
const e = printVuln(vulnerabilities[effect], c, vulnerabilities, printed, ' ')
if (e) {
output.push(...e.split('\n'))
}
}
if (indent === '') {
output.push('')
}
return output.map(l => `${indent}${l}`).join('\n')
}

View File

@@ -0,0 +1,75 @@
const colors = require('../colors.js')
const calculate = (data, { chalk }) => {
const c = colors(chalk)
const output = []
const { metadata: { vulnerabilities } } = data
const vulnCount = vulnerabilities.total
let someFixable = false
let someForceFixable = false
let forceFixSemVerMajor = false
let someUnfixable = false
if (vulnCount === 0) {
output.push(`found ${c.green('0')} vulnerabilities`)
} else {
for (const [, vuln] of Object.entries(data.vulnerabilities)) {
const { fixAvailable } = vuln
someFixable = someFixable || fixAvailable === true
someUnfixable = someUnfixable || fixAvailable === false
if (typeof fixAvailable === 'object') {
someForceFixable = true
forceFixSemVerMajor = forceFixSemVerMajor || fixAvailable.isSemVerMajor
}
}
const total = vulnerabilities.total
const sevs = Object.entries(vulnerabilities).filter(([s, count]) => {
return (s === 'low' || s === 'moderate' || s === 'high' || s === 'critical') &&
count > 0
})
if (sevs.length > 1) {
const severities = sevs.map(([s, count]) => {
return `${count} ${c.severity(s)}`
}).join(', ')
output.push(`${c.red(total)} vulnerabilities (${severities})`)
} else {
const [sev, count] = sevs[0]
output.push(`${count} ${c.severity(sev)} severity vulnerabilit${count === 1 ? 'y' : 'ies'}`)
}
// XXX use a different footer line if some aren't fixable easily.
// just 'run `npm audit` for details' maybe?
if (someFixable) {
output.push('', 'To address ' +
(someForceFixable || someUnfixable ? 'issues that do not require attention'
: 'all issues') + ', run:\n npm audit fix')
}
if (someForceFixable) {
output.push('', 'To address all issues' +
(someUnfixable ? ' possible' : '') +
(forceFixSemVerMajor ? ' (including breaking changes)' : '') +
', run:\n npm audit fix --force')
}
if (someUnfixable) {
output.push('',
'Some issues need review, and may require choosing',
'a different dependency.')
}
}
const summary = output.join('\n')
return {
summary,
report: vulnCount > 0 ? `${summary}\n\nRun \`npm audit\` for details.`
: summary,
}
}
module.exports = Object.assign((data, opt) => calculate(data, opt).report, {
summary: (data, opt) => calculate(data, opt).summary,
})

View File

@@ -0,0 +1 @@
module.exports = (data, { indent }) => JSON.stringify(data, null, indent)

View File

@@ -0,0 +1 @@
module.exports = () => ''