fix: validate registry path for allow-remote tarballs · npm/cli@bf623e0 · GitHub
Skip to content

Commit bf623e0

Browse files
Abhinav-143xowlstronaut
authored andcommitted
fix: validate registry path for allow-remote tarballs
1 parent a105799 commit bf623e0

3 files changed

Lines changed: 174 additions & 5 deletions

File tree

test/lib/commands/ci.js

Lines changed: 31 additions & 0 deletions

workspaces/arborist/lib/arborist/reify.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -844,17 +844,18 @@ module.exports = cls => class Reifier extends cls {
844844

845845
// When extracting a registry-resolved package, the spec we hand to pacote is name@URL.
846846
// pacote re-parses that with npa and gets spec.type === 'remote', so without an override the allow-remote gate would fire on every registry tarball (both =none and =root mis-fire).
847-
// Returns true only when we are confident this is a registry-mediated install: the node's inbound edges must all be registry-typed (no exotic spec smuggled the URL in) AND the resolved URL's host must match the registry npm-registry-fetch selected for this spec, so a tampered lockfile pointing at an attacker host still hits the gate.
847+
// Returns true only when we are confident this is a registry-mediated install.
848848
#isRegistryResolvedTarball (node) {
849849
if (!node.resolved || !node.isRegistryDependency) {
850850
return false
851851
}
852852
try {
853-
// Hostnames are case-insensitive; lowercase both sides for safety even though WHATWG URL already normalizes.
854-
const resolvedHost = new URL(node.resolved).hostname.toLowerCase()
853+
const resolved = new URL(node.resolved)
855854
// pickRegistry only consults spec.scope, so a bare-name (tag) parse is sufficient and avoids a node.version dependency.
856-
const registryHost = new URL(pickRegistry(npa(node.name), this.options)).hostname.toLowerCase()
857-
return resolvedHost === registryHost
855+
const registry = new URL(pickRegistry(npa(node.name), this.options))
856+
const registryPath = registry.pathname.replace(/\/?$/, '/')
857+
return resolved.origin === registry.origin &&
858+
(registryPath === '/' || resolved.pathname.startsWith(registryPath))
858859
} catch {
859860
return false
860861
}

workspaces/arborist/test/arborist/reify.js

Lines changed: 137 additions & 0 deletions

0 commit comments

Comments
 (0)