From 04ac3f2a83412da7ec5fdc5abe6f9fad2532da2b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 5 Oct 2026 10:02:48 -0700 Subject: [PATCH] [Fix] `nvm install`: do not remove the caller's `TMPDIR` after a failed download MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `nvm_install_binary` and `nvm_install_source` declared `local TMPDIR` without initializing it, and remove it with `rm -rf` on failure. dash's `local` keeps the caller's value, as does bash's when `TMPDIR` is passed as a prefix assignment (`TMPDIR=… nvm install`), so a failed download removed the caller's temp directory; on macOS, `tar` instead blocked reading the archive from the terminal. --- nvm.sh | 8 +++++ ...l_source do not remove an inherited TMPDIR | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100755 test/fast/Unit tests/nvm_install_binary and nvm_install_source do not remove an inherited TMPDIR diff --git a/nvm.sh b/nvm.sh index 6ec0d63b..8204b6d9 100755 --- a/nvm.sh +++ b/nvm.sh @@ -2775,8 +2775,12 @@ nvm_install_binary() { return 2 fi + # dash's `local` keeps the caller's value, and TMPDIR is usually set: it is + # later removed with `rm -rf`, so it must not start as the system temp dir local TARBALL + TARBALL='' local TMPDIR + TMPDIR='' local PROGRESS_BAR local NODE_OR_IOJS @@ -3176,9 +3180,13 @@ nvm_install_source() { fi fi + # see nvm_install_binary: these must not inherit TMPDIR, which is removed on failure local TARBALL + TARBALL='' local TMPDIR + TMPDIR='' local VERSION_PATH + VERSION_PATH='' if [ "${NVM_NO_PROGRESS-}" = "1" ]; then # --silent, --show-error, use short option as @samrocketman mentions the compatibility issue. diff --git a/test/fast/Unit tests/nvm_install_binary and nvm_install_source do not remove an inherited TMPDIR b/test/fast/Unit tests/nvm_install_binary and nvm_install_source do not remove an inherited TMPDIR new file mode 100755 index 00000000..90db055e --- /dev/null +++ b/test/fast/Unit tests/nvm_install_binary and nvm_install_source do not remove an inherited TMPDIR @@ -0,0 +1,30 @@ +#!/bin/sh + +WORK="${PWD}/nvm-inherited-tmpdir-work.$$" + +cleanup() { + command rm -rf "${WORK}" + unset -f cleanup die nvm_download_artifact +} +die () { echo "$@" ; cleanup ; exit 1; } + +: nvm.sh +\. ../../../nvm.sh + +nvm_download_artifact() { return 1; } + +make_canary() { + command rm -rf "${WORK}/tmp" + command mkdir -p "${WORK}/tmp" + echo canary > "${WORK}/tmp/canary" +} + +make_canary +TMPDIR="${WORK}/tmp" nvm_install_binary node std 8.0.0 0 < /dev/null > /dev/null 2>&1 +[ -f "${WORK}/tmp/canary" ] || die 'nvm_install_binary removed the TMPDIR it inherited after a failed download' + +make_canary +TMPDIR="${WORK}/tmp" nvm_install_source node std 8.0.0 < /dev/null > /dev/null 2>&1 +[ -f "${WORK}/tmp/canary" ] || die 'nvm_install_source removed the TMPDIR it inherited after a failed download' + +cleanup