From 01070e06060fd8c2c658ca7a9051d6cd1d94a8ee Mon Sep 17 00:00:00 2001 From: dipto0321 Date: Mon, 2 Nov 2026 09:52:45 +0600 Subject: [PATCH] fix(deps): bump the npm wrapper's tar to v7 and document npm 12's allowScripts gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two problems surfaced while verifying the v1.2.2 npm channel. **1. `tar` was pinned to a version with published advisories.** `nodeup-npm` pinned `tar@6.2.1`. npm itself flags it: npm warn deprecated tar@6.2.1: Old versions of tar are not supported, and contain widely publicized security vulnerabilities `npm audit` against the published wrapper reports **1 critical and 1 high** vulnerability, every one of them in `tar` — the hardlink path traversal, symlink poisoning, and PAX file-smuggling advisories. All of them sit on the archive-extraction path the wrapper uses to unpack the release tarball, which is the one place the wrapper touches untrusted bytes. Bumped to `tar@7.5.22`, past the advisory range (`<=7.5.20`). `npm audit` is now clean: **0 vulnerabilities**. The bump raises the wrapper's Node floor from 14 to 18, because `tar@7` declares `engines: { node: ">=18" }`. The wrapper's own code is unchanged and still runs on Node 14 — the floor comes from the dependency, so `engines` and the docs are updated to match. Verified end-to-end: the wrapper's real `extractTarGz()` (with its zip-slip `filter` guard) extracts the actual v1.2.2 release archive under `tar@7`, producing the binary at the expected 8423058 bytes. **2. npm 12 blocks the wrapper's install script.** npm 12 added `allowScripts`, which blocks install scripts for packages that aren't on an allowlist. `nodeupx` needs its `postinstall` to download the binary, so on npm 12+ a fresh `npm install -g nodeupx` finishes with the wrapper in place but **no binary** — `nodeup` never appears on `$PATH`, and the install log's warning scrolls past. The fix is `npm install-scripts approve nodeupx`. The wrapper README, the main README, and `docs/installation.md` now spell it out, with the permanent `~/.npmrc` form for anyone who wants it. --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ README.md | 8 +++++++- docs/installation.md | 2 +- nodeup-npm/README.md | 28 ++++++++++++++++++++++++++++ nodeup-npm/package.json | 6 +++--- 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41871bf..3c1e3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed +- The npm wrapper's `tar` dependency was pinned to `6.2.1`, which npm + itself flags as deprecated ("Old versions of tar are not supported, + and contain widely publicized security vulnerabilities"). `npm audit` + against the published wrapper reports **1 critical and 1 high** + vulnerability, all of them in `tar` — the hardlink-path-traversal, + symlink-poisoning, and file-smuggling advisories that apply to the + archive-extraction path the wrapper uses to unpack the release + tarball. + + Bumped to `tar@7.5.22`, which is past the advisory range + (`<=7.5.20`). `npm audit` is now clean: **0 vulnerabilities**. + + The bump raises the wrapper's Node floor from 14 to 18, because + `tar@7` declares `engines: { node: ">=18" }`. The wrapper's own + code is unchanged and still runs on Node 14 — the floor comes from + the dependency. + + Verified end-to-end: the wrapper's `extractTarGz` path (with its + zip-slip `filter` guard) extracts the real v1.2.2 release archive + correctly under `tar@7`, producing the binary at the expected size. + +### Added +- The npm wrapper README (and the main README / installation docs) now + explain npm 12's `allowScripts` gate. npm 12 **blocks install + scripts** for packages that aren't on an allowlist, and `nodeupx` + needs its `postinstall` to download the binary — so on npm 12+ a + fresh `npm install -g nodeupx` finishes with the wrapper in place + but **no binary** and `nodeup` missing from `$PATH`. The fix is + `npm install-scripts approve nodeupx`, which the docs now spell + out. + ## [1.2.2] - 2026-11-01 A patch release that **stops the snapshot leak**, gives the user diff --git a/README.md b/README.md index 276b599..e793606 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ scoop install nodeup Best for: Windows users who already use Scoop. The manifest is auto-managed by GoReleaser from `scoop: {}` in `.goreleaser.yaml`. -#### npm wrapper (any platform with Node ≥ 14) +#### npm wrapper (any platform with Node ≥ 18) ```bash npm install -g nodeupx @@ -116,6 +116,12 @@ dormant 2015 package (`romanmt/nodeup` — "a simple cluster implementation for node"). The downloaded binary still installs as the `nodeup` CLI on your `$PATH`. +> **npm 12+:** npm's `allowScripts` gate blocks install scripts for +> packages that aren't on an allowlist. `nodeupx` needs its +> `postinstall` to download the binary, so approve it once: +> `npm install-scripts approve nodeupx && npm install -g nodeupx`. +> See [`nodeup-npm/README.md`](./nodeup-npm/README.md#npm-12-approve-the-install-script). + Best for: anyone who treats their global npm install as the source of truth for CLI tools — typical in JavaScript / TypeScript projects. The wrapper is a thin downloader (`scripts/install.js`) that fetches diff --git a/docs/installation.md b/docs/installation.md index b98d1cc..748e21f 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -80,7 +80,7 @@ holds the manifest and is auto-pushed by GoReleaser. **Tradeoffs:** user-level install (no admin shell), upgrades via `scoop update nodeup`. Same Node-decoupled shape as Homebrew. -### npm wrapper (any platform with Node ≥ 14) +### npm wrapper (any platform with Node ≥ 18) ```bash npm install -g nodeupx diff --git a/nodeup-npm/README.md b/nodeup-npm/README.md index f16b4f4..c7ecab0 100644 --- a/nodeup-npm/README.md +++ b/nodeup-npm/README.md @@ -26,6 +26,34 @@ The `postinstall` script downloads a ~6 MB static Go binary into `node_modules/nodeup/bin/` and symlinks it onto your global `$PATH` as `nodeup`. No Go toolchain, no system services. +Requires **Node ≥ 18** (the `tar` dependency needs it). + +### npm 12+: approve the install script + +npm 12 added `allowScripts`, which **blocks install scripts** for +packages that aren't on an allowlist. `nodeupx` needs its +`postinstall` to download the binary, so on npm 12+ a fresh install +finishes with the wrapper in place but **no binary** — `nodeup` isn't +on your `$PATH`, and the install log says: + +``` +npm warn install-scripts 1 package had install scripts blocked because they are not covered by allowScripts: +npm warn install-scripts nodeupx@1.2.2 (preinstall: node scripts/check.js; postinstall: node scripts/install.js) +``` + +Approve the script and re-run the install: + +```bash +npm install-scripts approve nodeupx +npm install -g nodeupx +``` + +To approve it permanently, add it to your `~/.npmrc`: + +```ini +allow-scripts[]=nodeupx +``` + ## Who should use this wrapper **Pick the npm wrapper if you already live inside Node and want a diff --git a/nodeup-npm/package.json b/nodeup-npm/package.json index 5276ea7..2866693 100644 --- a/nodeup-npm/package.json +++ b/nodeup-npm/package.json @@ -24,7 +24,7 @@ "cli" ], "engines": { - "node": ">=14" + "node": ">=18" }, "bin": { "nodeup": "bin/nodeup" @@ -34,7 +34,7 @@ "preinstall": "node scripts/check.js" }, "dependencies": { - "tar": "^6.2.1" + "tar": "7.5.22" }, "files": [ "scripts/install.js", @@ -43,4 +43,4 @@ "LICENSE" ], "binaryVersion": "1.2.2" -} \ No newline at end of file +}