Socket
Socket
Sign inDemoInstall

pacote

Package Overview
Dependencies
Maintainers
6
Versions
220
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pacote - npm Package Compare versions

Comparing version 13.3.0 to 13.4.0

191

lib/registry.js

@@ -10,2 +10,3 @@ const Fetcher = require('./fetcher.js')

const ssri = require('ssri')
const crypto = require('crypto')

@@ -18,4 +19,2 @@ // Corgis are cute. 🐕🐶

// TODO: memoize reg requests, so we don't even have to check cache
const _headers = Symbol('_headers')

@@ -44,2 +43,10 @@ class RegistryFetcher extends Fetcher {

const parsed = new URL(this.registry)
const regKey = `//${parsed.host}${parsed.pathname}`
// unlike the nerf-darted auth keys, this one does *not* allow a mismatch
// of trailing slashes. It must match exactly.
if (this.opts[`${regKey}:_keys`]) {
this.registryKeys = this.opts[`${regKey}:_keys`]
}
// XXX pacote <=9 has some logic to ignore opts.resolved if

@@ -51,13 +58,6 @@ // the resolved URL doesn't go to the same registry.

resolve () {
if (this.resolved) {
return Promise.resolve(this.resolved)
}
// fetching the manifest sets resolved and (usually) integrity
return this.manifest().then(() => {
if (this.resolved) {
return this.resolved
}
async resolve () {
// fetching the manifest sets resolved and (if present) integrity
await this.manifest()
if (!this.resolved) {
throw Object.assign(

@@ -67,3 +67,4 @@ new Error('Invalid package manifest: no `dist.tarball` field'),

)
})
}
return this.resolved
}

@@ -95,9 +96,11 @@

// return the res.json() promise
const p = fetch(this.packumentUrl, {
...this.opts,
headers: this[_headers](),
spec: this.spec,
// never check integrity for packuments themselves
integrity: null,
}).then(res => res.json().then(packument => {
try {
const res = await fetch(this.packumentUrl, {
...this.opts,
headers: this[_headers](),
spec: this.spec,
// never check integrity for packuments themselves
integrity: null,
})
const packument = await res.json()
packument._cached = res.headers.has('x-local-cache')

@@ -109,74 +112,108 @@ packument._contentLength = +res.headers.get('content-length')

return packument
})).catch(er => {
} catch (err) {
if (this.packumentCache) {
this.packumentCache.delete(this.packumentUrl)
}
if (er.code === 'E404' && !this.fullMetadata) {
// possible that corgis are not supported by this registry
this.fullMetadata = true
return this.packument()
if (err.code !== 'E404' || this.fullMetadata) {
throw err
}
throw er
})
if (this.packumentCache) {
this.packumentCache.set(this.packumentUrl, p)
// possible that corgis are not supported by this registry
this.fullMetadata = true
return this.packument()
}
return p
}
manifest () {
async manifest () {
if (this.package) {
return Promise.resolve(this.package)
return this.package
}
return this.packument()
.then(packument => pickManifest(packument, this.spec.fetchSpec, {
...this.opts,
defaultTag: this.defaultTag,
before: this.before,
}) /* XXX add ETARGET and E403 revalidation of cached packuments here */)
.then(mani => {
// add _resolved and _integrity from dist object
const { dist } = mani
if (dist) {
this.resolved = mani._resolved = dist.tarball
mani._from = this.from
const distIntegrity = dist.integrity ? ssri.parse(dist.integrity)
: dist.shasum ? ssri.fromHex(dist.shasum, 'sha1', { ...this.opts })
: null
if (distIntegrity) {
if (!this.integrity) {
this.integrity = distIntegrity
} else if (!this.integrity.match(distIntegrity)) {
// only bork if they have algos in common.
// otherwise we end up breaking if we have saved a sha512
// previously for the tarball, but the manifest only
// provides a sha1, which is possible for older publishes.
// Otherwise, this is almost certainly a case of holding it
// wrong, and will result in weird or insecure behavior
// later on when building package tree.
for (const algo of Object.keys(this.integrity)) {
if (distIntegrity[algo]) {
throw Object.assign(new Error(
`Integrity checksum failed when using ${algo}: ` +
`wanted ${this.integrity} but got ${distIntegrity}.`
), { code: 'EINTEGRITY' })
}
}
// made it this far, the integrity is worthwhile. accept it.
// the setter here will take care of merging it into what we
// already had.
this.integrity = distIntegrity
const packument = await this.packument()
const mani = await pickManifest(packument, this.spec.fetchSpec, {
...this.opts,
defaultTag: this.defaultTag,
before: this.before,
})
/* XXX add ETARGET and E403 revalidation of cached packuments here */
// add _resolved and _integrity from dist object
const { dist } = mani
if (dist) {
this.resolved = mani._resolved = dist.tarball
mani._from = this.from
const distIntegrity = dist.integrity ? ssri.parse(dist.integrity)
: dist.shasum ? ssri.fromHex(dist.shasum, 'sha1', { ...this.opts })
: null
if (distIntegrity) {
if (this.integrity && !this.integrity.match(distIntegrity)) {
// only bork if they have algos in common.
// otherwise we end up breaking if we have saved a sha512
// previously for the tarball, but the manifest only
// provides a sha1, which is possible for older publishes.
// Otherwise, this is almost certainly a case of holding it
// wrong, and will result in weird or insecure behavior
// later on when building package tree.
for (const algo of Object.keys(this.integrity)) {
if (distIntegrity[algo]) {
throw Object.assign(new Error(
`Integrity checksum failed when using ${algo}: ` +
`wanted ${this.integrity} but got ${distIntegrity}.`
), { code: 'EINTEGRITY' })
}
}
}
if (this.integrity) {
mani._integrity = String(this.integrity)
if (dist.signatures) {
// made it this far, the integrity is worthwhile. accept it.
// the setter here will take care of merging it into what we already
// had.
this.integrity = distIntegrity
}
}
if (this.integrity) {
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} ` +
`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' })
}
}
mani._signatures = dist.signatures
}
// if no keys, don't set _signatures
} else {
mani._signatures = dist.signatures
}
this.package = rpj.normalize(mani)
return this.package
})
}
}
this.package = rpj.normalize(mani)
return this.package
}

@@ -183,0 +220,0 @@

{
"name": "pacote",
"version": "13.3.0",
"version": "13.4.0",
"description": "JavaScript package downloader",

@@ -29,3 +29,3 @@ "author": "GitHub Inc.",

"@npmcli/eslint-config": "^3.0.1",
"@npmcli/template-oss": "3.4.3",
"@npmcli/template-oss": "3.5.0",
"hosted-git-info": "^5.0.0",

@@ -78,5 +78,5 @@ "mutate-fs": "^2.1.1",

"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "3.4.3",
"version": "3.5.0",
"windowsCI": false
}
}

@@ -171,2 +171,6 @@ # pacote

when calling `@npmcli/run-script`.
* `verifySignatures` A boolean that will make pacote verify the
integrity signature of a manifest, if present. There must be a
configured `_keys` entry in the config that is scoped to the
registry the manifest is being fetched from.

@@ -173,0 +177,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc