Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: pacote@13.6.0 #4969

Merged
merged 1 commit into from Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 25 additions & 27 deletions node_modules/pacote/lib/fetcher.js
Expand Up @@ -18,6 +18,7 @@ const removeTrailingSlashes = require('./util/trailing-slashes.js')
const getContents = require('@npmcli/installed-package-contents')
const readPackageJsonFast = require('read-package-json-fast')
const readPackageJson = promisify(require('read-package-json'))
const Minipass = require('minipass')

// we only change ownership on unix platforms, and only if uid is 0
const selfOwner = process.getuid && process.getuid() === 0 ? {
Expand Down Expand Up @@ -105,15 +106,10 @@ class FetcherBase {
this[_readPackageJson] = readPackageJsonFast
}

// config values: npmjs (default), never, always
// we don't want to mutate the original value
if (opts.replaceRegistryHost !== 'never'
&& opts.replaceRegistryHost !== 'always'
) {
this.replaceRegistryHost = 'npmjs'
} else {
this.replaceRegistryHost = opts.replaceRegistryHost
}
// rrh is a registry hostname or 'never' or 'always'
// defaults to registry.npmjs.org
this.replaceRegistryHost = (!opts.replaceRegistryHost || opts.replaceRegistryHost === 'npmjs') ?
'registry.npmjs.org' : opts.replaceRegistryHost

this.defaultTag = opts.defaultTag || 'latest'
this.registry = removeTrailingSlashes(opts.registry || 'https://registry.npmjs.org')
Expand Down Expand Up @@ -224,40 +220,42 @@ class FetcherBase {
}

[_istream] (stream) {
// everyone will need one of these, either for verifying or calculating
// We always set it, because we have might only have a weak legacy hex
// sha1 in the packument, and this MAY upgrade it to a stronger algo.
// If we had an integrity, and it doesn't match, then this does not
// override that error; the istream will raise the error before it
// gets to the point of re-setting the integrity.
const istream = ssri.integrityStream(this.opts)
istream.on('integrity', i => this.integrity = i)
stream.on('error', er => istream.emit('error', er))

// if not caching this, just pipe through to the istream and return it
// if not caching this, just return it
if (!this.opts.cache || !this[_cacheFetches]) {
// instead of creating a new integrity stream, we only piggyback on the
// provided stream's events
if (stream.hasIntegrityEmitter) {
stream.on('integrity', i => this.integrity = i)
return stream
}

const istream = ssri.integrityStream(this.opts)
istream.on('integrity', i => this.integrity = i)
stream.on('error', err => istream.emit('error', err))
return stream.pipe(istream)
}

// we have to return a stream that gets ALL the data, and proxies errors,
// but then pipe from the original tarball stream into the cache as well.
// To do this without losing any data, and since the cacache put stream
// is not a passthrough, we have to pipe from the original stream into
// the cache AFTER we pipe into the istream. Since the cache stream
// the cache AFTER we pipe into the middleStream. Since the cache stream
// has an asynchronous flush to write its contents to disk, we need to
// defer the istream end until the cache stream ends.
stream.pipe(istream, { end: false })
// defer the middleStream end until the cache stream ends.
const middleStream = new Minipass()
stream.on('error', err => middleStream.emit('error', err))
stream.pipe(middleStream, { end: false })
const cstream = cacache.put.stream(
this.opts.cache,
`pacote:tarball:${this.from}`,
this.opts
)
cstream.on('integrity', i => this.integrity = i)
cstream.on('error', err => stream.emit('error', err))
stream.pipe(cstream)
// defer istream end until after cstream
// cache write errors should not crash the fetch, this is best-effort.
cstream.promise().catch(() => {}).then(() => istream.end())

return istream
cstream.promise().catch(() => {}).then(() => middleStream.end())
return middleStream
}

pickIntegrityAlgorithm () {
Expand Down
77 changes: 41 additions & 36 deletions node_modules/pacote/lib/registry.js
Expand Up @@ -122,11 +122,12 @@ class RegistryFetcher extends Fetcher {
}

const packument = await this.packument()
const mani = await pickManifest(packument, this.spec.fetchSpec, {
let mani = await pickManifest(packument, this.spec.fetchSpec, {
...this.opts,
defaultTag: this.defaultTag,
before: this.before,
})
mani = rpj.normalize(mani)
/* XXX add ETARGET and E403 revalidation of cached packuments here */

// add _resolved and _integrity from dist object
Expand Down Expand Up @@ -165,49 +166,53 @@ class RegistryFetcher extends Fetcher {
mani._integrity = String(this.integrity)
if (dist.signatures) {
if (this.opts.verifySignatures) {
if (this.registryKeys) {
// validate and throw on error, then set _signatures
const message = `${mani._id}:${mani._integrity}`
for (const signature of dist.signatures) {
const publicKey = this.registryKeys.filter(key => (key.keyid === signature.keyid))[0]
if (!publicKey) {
throw Object.assign(new Error(
`${mani._id} has a signature with keyid: ${signature.keyid} ` +
'but no corresponding public key can be found.'
), { code: 'EMISSINGSIGNATUREKEY' })
}
const validPublicKey =
!publicKey.expires || (Date.parse(publicKey.expires) > Date.now())
if (!validPublicKey) {
throw Object.assign(new Error(
`${mani._id} has a signature with keyid: ${signature.keyid} ` +
// validate and throw on error, then set _signatures
const message = `${mani._id}:${mani._integrity}`
for (const signature of dist.signatures) {
const publicKey = this.registryKeys &&
this.registryKeys.filter(key => (key.keyid === signature.keyid))[0]
if (!publicKey) {
throw Object.assign(new Error(
`${mani._id} has a registry signature with keyid: ${signature.keyid} ` +
'but no corresponding public key can be found'
), { code: 'EMISSINGSIGNATUREKEY' })
}
const validPublicKey =
!publicKey.expires || (Date.parse(publicKey.expires) > Date.now())
if (!validPublicKey) {
throw Object.assign(new Error(
`${mani._id} has a registry signature with keyid: ${signature.keyid} ` +
`but the corresponding public key has expired ${publicKey.expires}`
), { code: 'EEXPIREDSIGNATUREKEY' })
}
const verifier = crypto.createVerify('SHA256')
verifier.write(message)
verifier.end()
const valid = verifier.verify(
publicKey.pemkey,
signature.sig,
'base64'
)
if (!valid) {
throw Object.assign(new Error(
'Integrity checksum signature failed: ' +
`key ${publicKey.keyid} signature ${signature.sig}`
), { code: 'EINTEGRITYSIGNATURE' })
}
), { code: 'EEXPIREDSIGNATUREKEY' })
}
const verifier = crypto.createVerify('SHA256')
verifier.write(message)
verifier.end()
const valid = verifier.verify(
publicKey.pemkey,
signature.sig,
'base64'
)
if (!valid) {
throw Object.assign(new Error(
`${mani._id} has an invalid registry signature with ` +
`keyid: ${publicKey.keyid} and signature: ${signature.sig}`
), {
code: 'EINTEGRITYSIGNATURE',
keyid: publicKey.keyid,
signature: signature.sig,
resolved: mani._resolved,
integrity: mani._integrity,
})
}
mani._signatures = dist.signatures
}
// if no keys, don't set _signatures
mani._signatures = dist.signatures
} else {
mani._signatures = dist.signatures
}
}
}
this.package = rpj.normalize(mani)
this.package = mani
return this.package
}

Expand Down
27 changes: 14 additions & 13 deletions node_modules/pacote/lib/remote.js
Expand Up @@ -4,8 +4,6 @@ const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
const pacoteVersion = require('../package.json').version
const fetch = require('npm-registry-fetch')
const Minipass = require('minipass')
// The default registry URL is a string of great magic.
const magicHost = 'https://registry.npmjs.org'

const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
const _headers = Symbol('_headers')
Expand All @@ -14,11 +12,9 @@ class RemoteFetcher extends Fetcher {
super(spec, opts)
this.resolved = this.spec.fetchSpec
const resolvedURL = new URL(this.resolved)
if (
(this.replaceRegistryHost === 'npmjs'
&& resolvedURL.origin === magicHost)
|| this.replaceRegistryHost === 'always'
) {
if (this.replaceRegistryHost !== 'never'
&& (this.replaceRegistryHost === 'always'
|| this.replaceRegistryHost === resolvedURL.host)) {
this.resolved = new URL(resolvedURL.pathname, this.registry).href
}

Expand All @@ -35,23 +31,28 @@ class RemoteFetcher extends Fetcher {

[_tarballFromResolved] () {
const stream = new Minipass()
stream.hasIntegrityEmitter = true

const fetchOpts = {
...this.opts,
headers: this[_headers](),
spec: this.spec,
integrity: this.integrity,
algorithms: [this.pickIntegrityAlgorithm()],
}
fetch(this.resolved, fetchOpts).then(res => {
const hash = res.headers.get('x-local-cache-hash')
if (hash) {
this.integrity = decodeURIComponent(hash)
}

fetch(this.resolved, fetchOpts).then(res => {
res.body.on('error',
/* istanbul ignore next - exceedingly rare and hard to simulate */
er => stream.emit('error', er)
).pipe(stream)
)

res.body.on('integrity', i => {
this.integrity = i
stream.emit('integrity', i)
})

res.body.pipe(stream)
}).catch(er => stream.emit('error', er))

return stream
Expand Down
5 changes: 2 additions & 3 deletions node_modules/pacote/package.json
@@ -1,6 +1,6 @@
{
"name": "pacote",
"version": "13.5.0",
"version": "13.6.0",
"description": "JavaScript package downloader",
"author": "GitHub Inc.",
"bin": {
Expand All @@ -21,8 +21,7 @@
"template-oss-apply": "template-oss-apply --force"
},
"tap": {
"timeout": 300,
"coverage-map": "map.js"
"timeout": 300
},
"devDependencies": {
"@npmcli/eslint-config": "^3.0.1",
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json
Expand Up @@ -138,7 +138,7 @@
"npm-user-validate": "^1.0.1",
"npmlog": "^6.0.2",
"opener": "^1.5.2",
"pacote": "^13.4.1",
"pacote": "^13.6.0",
"parse-conflict-json": "^2.0.2",
"proc-log": "^2.0.1",
"qrcode-terminal": "^0.12.0",
Expand Down Expand Up @@ -5547,9 +5547,9 @@
}
},
"node_modules/pacote": {
"version": "13.5.0",
"resolved": "https://registry.npmjs.org/pacote/-/pacote-13.5.0.tgz",
"integrity": "sha512-yekp0ykEsaBH0t0bYA/89R+ywdYV5ZnEdg4YMIfqakSlpIhoF6b8+aEUm8NZpfWRgmy6lxgywcW05URhLRogVQ==",
"version": "13.6.0",
"resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.0.tgz",
"integrity": "sha512-zHmuCwG4+QKnj47LFlW3LmArwKoglx2k5xtADiMCivVWPgNRP5QyLDGOIjGjwOe61lhl1rO63m/VxT16pEHLWg==",
"inBundle": true,
"dependencies": {
"@npmcli/git": "^3.0.0",
Expand Down Expand Up @@ -13877,9 +13877,9 @@
}
},
"pacote": {
"version": "13.5.0",
"resolved": "https://registry.npmjs.org/pacote/-/pacote-13.5.0.tgz",
"integrity": "sha512-yekp0ykEsaBH0t0bYA/89R+ywdYV5ZnEdg4YMIfqakSlpIhoF6b8+aEUm8NZpfWRgmy6lxgywcW05URhLRogVQ==",
"version": "13.6.0",
"resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.0.tgz",
"integrity": "sha512-zHmuCwG4+QKnj47LFlW3LmArwKoglx2k5xtADiMCivVWPgNRP5QyLDGOIjGjwOe61lhl1rO63m/VxT16pEHLWg==",
"requires": {
"@npmcli/git": "^3.0.0",
"@npmcli/installed-package-contents": "^1.0.7",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -107,7 +107,7 @@
"npm-user-validate": "^1.0.1",
"npmlog": "^6.0.2",
"opener": "^1.5.2",
"pacote": "^13.4.1",
"pacote": "^13.6.0",
"parse-conflict-json": "^2.0.2",
"proc-log": "^2.0.1",
"qrcode-terminal": "^0.12.0",
Expand Down