From 00217de1e176d0ae522dd1f5ab088024a600dc5f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 18 Oct 2026 23:18:20 -0700 Subject: [PATCH] [Fix] `install.sh`: don't let a git repository in the current directory affect `git ls-remote` `install_nvm_from_git` checked whether `$NVM_INSTALL_VERSION` is a ref with a bare `git ls-remote`, which discovers and loads the config of whatever repository contains the current directory. That repository's `url.*.insteadOf` and `core.sshCommand` could then redirect or hijack the check, unlike every other git command in the function, which already passes `--git-dir="$INSTALL_DIR"/.git`. Pass `--git-dir` here too; `ls-remote` works even when that directory does not exist yet, as on a fresh install Discovered by Anthropic's OSS Scanner, as ANT-2026-JS4YHKRK; the scanner reported it as a vulnerability, but it is not one. --- install.sh | 2 +- .../install_nvm_from_git_ignores_cwd_repo | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100755 test/install_script/install_nvm_from_git_ignores_cwd_repo diff --git a/install.sh b/install.sh index 0b69d205..9e66a31a 100755 --- a/install.sh +++ b/install.sh @@ -157,7 +157,7 @@ install_nvm_from_git() { NVM_VERSION="${NVM_INSTALL_VERSION:-$(nvm_latest_version)}" if [ -n "${NVM_INSTALL_VERSION:-}" ]; then # Check if version is an existing ref - if command git ls-remote "$(nvm_source "git")" "$NVM_VERSION" | nvm_grep -q -e "$NVM_VERSION" ; then + if command git --git-dir="$INSTALL_DIR"/.git ls-remote "$(nvm_source "git")" "$NVM_VERSION" | nvm_grep -q -e "$NVM_VERSION" ; then : # Check if version is an existing changeset elif ! nvm_download -o /dev/null "$(nvm_source "script-nvm-exec")"; then diff --git a/test/install_script/install_nvm_from_git_ignores_cwd_repo b/test/install_script/install_nvm_from_git_ignores_cwd_repo new file mode 100755 index 00000000..faa3020d --- /dev/null +++ b/test/install_script/install_nvm_from_git_ignores_cwd_repo @@ -0,0 +1,64 @@ +#!/bin/sh + +SAVE_NVM_DIR="$NVM_DIR" +SAVE_NVM_SOURCE="$NVM_SOURCE" +SAVE_NVM_INSTALL_VERSION="$NVM_INSTALL_VERSION" +WORK="$PWD/install_nvm_from_git-cwd-repo-work.$$" +UPSTREAM="$WORK/upstream" +PROJECT="$WORK/project" +MARKER="$WORK/cwd-repo-config-was-read" + +cleanup() { + NVM_DIR="$SAVE_NVM_DIR" + NVM_SOURCE="$SAVE_NVM_SOURCE" + NVM_INSTALL_VERSION="$SAVE_NVM_INSTALL_VERSION" + unset SAVE_NVM_DIR SAVE_NVM_SOURCE SAVE_NVM_INSTALL_VERSION + rm -rf "$WORK" + unset -f die cleanup +} +die () { echo "$@" ; cleanup ; exit 1; } + +NVM_ENV=testing \. ../../install.sh + +git_commit() { + git -c user.name=nvm -c user.email=nvm@example.invalid -c commit.gpgsign=false "$@" +} + +# a local stand-in for the nvm repo, so the install needs no network +mkdir -p "$UPSTREAM" || die 'Unable to create upstream directory' +cp ../../nvm.sh ../../nvm-exec ../../bash_completion "$UPSTREAM"/ || die 'Unable to copy nvm files' +git init --quiet "$UPSTREAM" || die 'Unable to init upstream' +git --git-dir="$UPSTREAM/.git" --work-tree="$UPSTREAM" add nvm.sh nvm-exec bash_completion || die 'Unable to add upstream files' +git_commit --git-dir="$UPSTREAM/.git" --work-tree="$UPSTREAM" commit --quiet -m 'release' || die 'Unable to commit upstream' +git --git-dir="$UPSTREAM/.git" tag v9.9.9 || die 'Unable to tag upstream' +EXPECTED="$(git --git-dir="$UPSTREAM/.git" rev-parse --verify 'v9.9.9^{commit}')" + +# an unrelated repository in the current directory, whose own config rewrites +# the nvm source URL; it must have no effect on installing nvm +git init --quiet "$PROJECT" || die 'Unable to init project' +mkdir -p "$PROJECT/sub" || die 'Unable to create project subdirectory' +git --git-dir="$PROJECT/.git" config url."ssh://example.invalid/nvm.git".insteadOf "$UPSTREAM" || die 'Unable to set insteadOf' +git --git-dir="$PROJECT/.git" config core.sshCommand "touch '$MARKER'; false" || die 'Unable to set core.sshCommand' + +for CWD in "$PROJECT" "$PROJECT/sub"; do + rm -f "$MARKER" + NVM_DIR="$WORK/nvm" + rm -rf "$NVM_DIR" + OUTPUT="$(cd "$CWD" && NVM_SOURCE="$UPSTREAM" NVM_INSTALL_VERSION=v9.9.9 install_nvm_from_git 2>&1)" + EXIT_CODE=$? + + [ ! -e "$MARKER" ] || die "install_nvm_from_git, run from '$CWD', used the git config of the repository in the current directory" + [ "$EXIT_CODE" = 0 ] || die "install_nvm_from_git, run from '$CWD', exited with $EXIT_CODE; output: $OUTPUT" + ACTUAL="$(git --git-dir="$NVM_DIR/.git" rev-parse --verify HEAD)" + [ "$ACTUAL" = "$EXPECTED" ] || die "install_nvm_from_git, run from '$CWD', checked out '$ACTUAL', expected '$EXPECTED'" +done + +# an update of an existing install must not use the current directory's repository config either +rm -f "$MARKER" +OUTPUT="$(cd "$PROJECT" && NVM_SOURCE="$UPSTREAM" NVM_INSTALL_VERSION=v9.9.9 install_nvm_from_git 2>&1)" +EXIT_CODE=$? +[ ! -e "$MARKER" ] || die 'install_nvm_from_git, updating an existing install, used the git config of the repository in the current directory' +[ "$EXIT_CODE" = 0 ] || die "install_nvm_from_git, updating an existing install, exited with $EXIT_CODE; output: $OUTPUT" + +unset -f git_commit +cleanup