Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2020-08-11 00:35:15 +0300
committerisaacs <i@izs.me>2020-08-11 00:35:15 +0300
commit3598fe1f2dfe6c55221bbac8aaf21feab74a936a (patch)
treef6b2a76b44947d3ad52124854aacab01f487556d
parent5fb217701c060e37a3fb4a2e985f80fb015157b9 (diff)
@npmcli/arborist@0.0.16
This adds support for `npm audit --production`, by having Arborist respect the `omit` option when running audit reports.
-rw-r--r--node_modules/@npmcli/arborist/lib/arborist/reify.js3
-rw-r--r--node_modules/@npmcli/arborist/lib/audit-report.js90
-rw-r--r--node_modules/@npmcli/arborist/lib/vuln.js9
-rw-r--r--node_modules/@npmcli/arborist/package.json2
-rw-r--r--package-lock.json14
-rw-r--r--package.json2
6 files changed, 87 insertions, 33 deletions
diff --git a/node_modules/@npmcli/arborist/lib/arborist/reify.js b/node_modules/@npmcli/arborist/lib/arborist/reify.js
index 01cbccc80..ddbfc6d62 100644
--- a/node_modules/@npmcli/arborist/lib/arborist/reify.js
+++ b/node_modules/@npmcli/arborist/lib/arborist/reify.js
@@ -225,7 +225,6 @@ module.exports = cls => class Reifier extends cls {
const paths = [ node.path, ...node.binPaths ]
const moves = this[_retiredPaths]
this.log.silly('reify', 'mark', retire ? 'retired' : 'deleted', paths)
- node.parent = null
for (const path of paths) {
if (retire) {
const retired = retirePath(path)
@@ -412,6 +411,7 @@ module.exports = cls => class Reifier extends cls {
if (!res) {
node.parent = null
this.log.verbose('reify', 'unrecognized node in tree', node.path)
+ node.parent = null
this[_addNodeToTrashList](node)
return
}
@@ -625,6 +625,7 @@ module.exports = cls => class Reifier extends cls {
}
}
for (const shadow of bundleShadowed) {
+ shadow.parent = null
this[_addNodeToTrashList](shadow)
}
}
diff --git a/node_modules/@npmcli/arborist/lib/audit-report.js b/node_modules/@npmcli/arborist/lib/audit-report.js
index c9989518f..7ca8653d4 100644
--- a/node_modules/@npmcli/arborist/lib/audit-report.js
+++ b/node_modules/@npmcli/arborist/lib/audit-report.js
@@ -3,7 +3,8 @@
const npa = require('npm-package-arg')
const pickManifest = require('npm-pick-manifest')
const pacote = require('pacote')
-const semver = require('semver')
+const {intersects, satisfies, simplifyRange} = require('semver')
+const semverOpt = { loose: true, includePrerelease: true }
const Vuln = require('./vuln.js')
@@ -22,6 +23,7 @@ const _packument = Symbol('packument')
const _packuments = Symbol('packuments')
const _getDepSpec = Symbol('getDepSpec')
const _init = Symbol('init')
+const _omit = Symbol('omit')
const procLog = require('./proc-log.js')
const fetch = require('npm-registry-fetch')
@@ -95,6 +97,7 @@ class AuditReport extends Map {
this[_specVulnerableMemo] = new Map()
this[_vulnDependents] = new Set()
this[_packuments] = new Map()
+ this[_omit] = new Set(opts.omit || [])
this.topVulns = new Map()
this.advisoryVulns = new Map()
this.dependencyVulns = new Map()
@@ -179,7 +182,7 @@ class AuditReport extends Map {
// if it's a bundle dep, then we must avoid it if the vulnerable
// range and the dep range intersect, since we can't update in-place.
if (bundled) {
- const val = semver.intersects(spec, avoid, { includePrerelease: true })
+ const val = intersects(spec, avoid, { includePrerelease: true })
if (val)
this[_specVulnerableMemo].set(key, val)
return val
@@ -309,7 +312,7 @@ class AuditReport extends Map {
}
}
- const mvr = semver.simplifyRange(versions, metaVuln.join(' || '), {
+ const mvr = simplifyRange(versions, metaVuln.join(' || '), {
includePrerelease:true,
})
await this[_addVulnerability](p.name, mvr, vuln)
@@ -386,10 +389,22 @@ class AuditReport extends Map {
// wrap in try/finally to ensure we end the timer properly
// and don't leave it hanging to conflict with a future one.
try {
+ // we always treat metavulns as relevant. just check advisories
+ // that might not apply to this tree, given omit options.
+ let relevant = via instanceof Vuln
process.emit('time', `auditReport:add:${name}@${range}`)
for (const node of this.tree.inventory.query('name', name)) {
- if (vuln.nodes.has(node) || !vuln.isVulnerable(node))
+ if (shouldOmit(node, this[_omit]))
+ continue
+
+ // check if this node would be affected by the advisory or metavuln
+ if (!relevant) {
+ const { version } = node.package
+ relevant = version && satisfies(version, range, semverOpt)
+ }
+
+ if (!vuln.isVulnerable(node))
continue
for (const {from} of node.edgesIn) {
@@ -400,10 +415,16 @@ class AuditReport extends Map {
// if we didn't get anything, then why is this even here??
// this can happen if you are loading from a lockfile created by
// npm v5, since it lists the current version of all deps,
- // rather than the range that is actually depended upon.
+ // rather than the range that is actually depended upon,
+ // or if using --omit with the older audit endpoint.
if (vuln.nodes.size === 0)
return this.delete(name)
+ // if the vuln is valid, but THIS vuln isn't relevant, remove it
+ // from the via list. happens when using omit with old endpoint.
+ if (!relevant)
+ vuln.deleteVia(via)
+
if (!vuln.packument)
vuln.packument = await this[_packument](name)
} finally {
@@ -447,27 +468,32 @@ class AuditReport extends Map {
try {
try {
// first try the super fast bulk advisory listing
+ const body = prepareBulkData(this.tree, this[_omit])
+
+ // no sense asking if we don't have anything to audit
+ if (!Object.keys(body).length)
+ return {}
+
const res = await fetch('/-/npm/v1/security/advisories/bulk', {
...this.options,
registry: this.options.auditRegistry || this.options.registry,
method: 'POST',
gzip: true,
- body: prepareBulkData(this.tree, this.options),
+ body,
})
return await res.json()
} catch (_) {
// that failed, try the quick audit endpoint
-
+ const body = prepareData(this.tree, this.options)
const res = await fetch('/-/npm/v1/security/audits/quick', {
...this.options,
registry: this.options.auditRegistry || this.options.registry,
method: 'POST',
gzip: true,
- body: prepareData(this.tree, this.options),
+ body,
})
-
- return await res.json().then(report => AuditReport.auditToBulk(report))
+ return AuditReport.auditToBulk(await res.json())
}
} catch (er) {
this.log.verbose('audit error', er)
@@ -480,14 +506,26 @@ class AuditReport extends Map {
}
}
-const prepareBulkData = (tree, opts) => {
+// return true if we should ignore this one
+const shouldOmit = (node, omit) =>
+ omit.size === 0 ? false
+ : node.dev && omit.has('dev') ||
+ node.optional && omit.has('optional') ||
+ node.devOptional && omit.has('dev') && omit.has('optional') ||
+ node.peer && omit.has('peer')
+
+const prepareBulkData = (tree, omit) => {
const payload = {}
for (const name of tree.inventory.query('name')) {
const set = new Set()
for (const node of tree.inventory.query('name', name)) {
+ if (shouldOmit(node, omit))
+ continue
+
set.add(node.version)
}
- payload[name] = [...set]
+ if (set.size)
+ payload[name] = [...set]
}
return payload
}
@@ -498,20 +536,26 @@ const prepareData = (tree, opts) => {
const { platform, arch } = process
const { NODE_ENV: node_env } = process.env
const data = tree.meta.commit()
- return JSON.stringify({
- ...data,
+ // the legacy audit endpoint doesn't support any kind of pre-filtering
+ // we just have to get the advisories and skip over them in the report
+ return {
+ name: data.name,
+ version: data.version,
requires: {
...(tree.package.devDependencies || {}),
- ...(tree.package.peerDependencies|| {}),
- ...(tree.package.optionalDependencies|| {}),
- ...(tree.package.dependencies|| {}),
+ ...(tree.package.peerDependencies || {}),
+ ...(tree.package.optionalDependencies || {}),
+ ...(tree.package.dependencies || {}),
+ },
+ dependencies: data.dependencies,
+ metadata: {
+ node_version,
+ npm_version,
+ platform,
+ arch,
+ node_env,
},
- node_version,
- npm_version,
- platform,
- arch,
- node_env,
- }, 0, 2)
+ }
}
module.exports = AuditReport
diff --git a/node_modules/@npmcli/arborist/lib/vuln.js b/node_modules/@npmcli/arborist/lib/vuln.js
index 3b5f3756e..ce656c09b 100644
--- a/node_modules/@npmcli/arborist/lib/vuln.js
+++ b/node_modules/@npmcli/arborist/lib/vuln.js
@@ -76,6 +76,15 @@ class Vuln {
}
}
+ deleteVia (via) {
+ this.via.delete(via)
+ // make sure we have the max severity of all the vulns causing this one
+ this.severity = null
+ for (const via of this.via) {
+ this.addVia(via)
+ }
+ }
+
addVia (via) {
this.via.add(via)
const sev = severities.get(via.severity)
diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json
index 7f4df9eba..8de553e1a 100644
--- a/node_modules/@npmcli/arborist/package.json
+++ b/node_modules/@npmcli/arborist/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/arborist",
- "version": "0.0.15",
+ "version": "0.0.16",
"description": "Manage node_modules trees",
"dependencies": {
"@npmcli/installed-package-contents": "^1.0.5",
diff --git a/package-lock.json b/package-lock.json
index 915a1cec5..eb020bd6c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -87,7 +87,7 @@
],
"license": "Artistic-2.0",
"dependencies": {
- "@npmcli/arborist": "^0.0.15",
+ "@npmcli/arborist": "^0.0.16",
"@npmcli/ci-detect": "^1.2.0",
"@npmcli/run-script": "^1.4.0",
"abbrev": "~1.1.1",
@@ -395,9 +395,9 @@
"dev": true
},
"node_modules/@npmcli/arborist": {
- "version": "0.0.15",
- "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.15.tgz",
- "integrity": "sha512-z/vBh3WXNQTz2DBcNYlA9aA5Jbh7Q3C6WQ0iBJS1FjshrtvlkTp3vaRQS/koSRVl1P2Q6f5sCAJLraU44Q5CEA==",
+ "version": "0.0.16",
+ "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.16.tgz",
+ "integrity": "sha512-Bou0VolPtTjQq63wIFYHoyub09HEz2u4aPdF1gUHJu7ZjOf+PcMmxdX9L/ULe3E11/JvRK6Tp6x/lnY92uG8LA==",
"inBundle": true,
"dependencies": {
"@npmcli/installed-package-contents": "^1.0.5",
@@ -9429,9 +9429,9 @@
"dev": true
},
"@npmcli/arborist": {
- "version": "0.0.15",
- "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.15.tgz",
- "integrity": "sha512-z/vBh3WXNQTz2DBcNYlA9aA5Jbh7Q3C6WQ0iBJS1FjshrtvlkTp3vaRQS/koSRVl1P2Q6f5sCAJLraU44Q5CEA==",
+ "version": "0.0.16",
+ "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-0.0.16.tgz",
+ "integrity": "sha512-Bou0VolPtTjQq63wIFYHoyub09HEz2u4aPdF1gUHJu7ZjOf+PcMmxdX9L/ULe3E11/JvRK6Tp6x/lnY92uG8LA==",
"requires": {
"@npmcli/installed-package-contents": "^1.0.5",
"@npmcli/map-workspaces": "0.0.0-pre.1",
diff --git a/package.json b/package.json
index 98a8378ac..42b9e026f 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"./package.json": "./package.json"
},
"dependencies": {
- "@npmcli/arborist": "^0.0.15",
+ "@npmcli/arborist": "^0.0.16",
"@npmcli/ci-detect": "^1.2.0",
"@npmcli/run-script": "^1.4.0",
"abbrev": "~1.1.1",