Files
nvm/test/fast/Unit tests/nvm_die_on_prefix
T
Jordan Harband 4049296ca8 [Fix] nvm_die_on_prefix: never let a project .npmrc choose which npmrc file --delete-prefix edits
`nvm use --delete-prefix`, which nvm itself recommends when it finds a `prefix` or `globalconfig` setting, ran `npm config delete` from the current directory.
For a project `.npmrc`, it ran a bare `npm config delete prefix`/`globalconfig`, so npm loaded that untrusted file first, and its `userconfig`, `globalconfig`, or `location=global` keys picked which file npm rewrote, deleted, or chmodded to 0666 - eg, `~/.bashrc` or `~/.aws/credentials`.
The builtin and user branches pinned `--userconfig`, but still loaded the project file, so a project `location=global` plus an indented ` globalconfig=` (which nvm's check does not match) redirected those writes the same way.
`npm config delete` never edits the project file anyway, so that branch could not do what it claimed.

For the project npmrc, no longer run npm at all: with `--delete-prefix`, warn that project npmrc files are not modified and must be edited by hand, and continue, as before.
For the builtin, global, and user npmrc files, pass `--prefix` set to the version directory, so npm does not walk up from the current directory to load the project npmrc, and its global config resolves to that version's `etc/npmrc`.

Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-WYRTKBQ5.
2026-10-16 20:08:01 -07:00

310 lines
16 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
TEST_PWD=$(pwd)
TEST_DIR="$TEST_PWD/nvm_die_on_prefix_tmp"
: nvm.sh
\. ../../../nvm.sh
\. ../../common.sh
TEST_VERSION_DIR="${TEST_DIR}/version"
cleanup () {
rm -rf "$TEST_DIR"
alias nvm_has='\nvm_has'
alias npm='\npm'
unset -f nvm_has npm node
}
die () {
echo "$@";
cleanup;
exit 1;
}
[ ! -e "$TEST_DIR" ] && mkdir "$TEST_DIR"
try_err nvm_die_on_prefix
EXPECTED_OUTPUT="First argument \"delete the prefix\" must be zero or one"
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_1" ] || die "'nvm_die_on_prefix' did not exit with 1; got "$CAPTURED_EXIT_CODE""
try_err nvm_die_on_prefix 2
EXPECTED_OUTPUT="First argument \"delete the prefix\" must be zero or one"
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 2' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_1" ] || die "'nvm_die_on_prefix' did not exit with 1; got "$CAPTURED_EXIT_CODE""
try_err nvm_die_on_prefix 0
EXPECTED_OUTPUT='Second argument "nvm command", and third argument "nvm version dir", must both be nonempty'
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_2" ] || die "'nvm_die_on_prefix 0' did not exit with 2; got '$CAPTURED_EXIT_CODE'"
nvm_has() { return 1; } # ie, npm is not installed
OUTPUT="$(nvm_die_on_prefix 0 version_dir foo 2>&1)"
[ -z "$OUTPUT" ] || die "nvm_die_on_prefix was not a noop when nvm_has returns 1, got '$OUTPUT'"
nvm_has() { return 0; }
OUTPUT="$(nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' was not a noop when prefix is good; got '$OUTPUT'"
# `nvm_get_os` runs `uname`; it is only needed when an `NPM_CONFIG_PREFIX`
# variable is set, so with none set it must not run at all
MOCK_BIN="${TEST_DIR}/bin"
mkdir -p "${MOCK_BIN}"
{
echo '#!/bin/sh'
echo 'echo "uname was called" >&2'
echo 'exit 1'
} > "${MOCK_BIN}/uname"
chmod +x "${MOCK_BIN}/uname"
unset NPM_CONFIG_PREFIX npm_config_prefix npm_CONFIG_PREFIX
OUTPUT="$(PATH="${MOCK_BIN}:${PATH}" nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' detected the OS (ran uname) when no NPM_CONFIG_PREFIX was set; got '$OUTPUT'"
mkdir -p "$(nvm_version_dir new)"
ln -s "$(nvm_version_dir new)" "$TEST_DIR/node"
npm() {
local args
args="$@"
if [ "_$args" = "_config --loglevel=warn get prefix" ]; then
echo "$TEST_DIR/node"
fi
}
node() {
if [ "_$1" = "_-v" ]; then
echo "v0.0.0"
fi
}
OUTPUT="$(nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' was not a noop when directory is equivalent; got '$OUTPUT'"
PREFIX=bar try_err nvm_die_on_prefix 0 foo "$(nvm_version_dir new)"
unset PREFIX
EXPECTED_OUTPUT='nvm is not compatible with the "PREFIX" environment variable: currently set to "bar"
Run `unset PREFIX` to unset it.'
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'PREFIX=bar nvm_die_on_prefix 0 foo' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_3" ] || die "'PREFIX=bar nvm_die_on_prefix 0 foo' did not exit with 3; got '$CAPTURED_EXIT_CODE'"
NPM_CONFIG_PREFIX=bar try_err nvm_die_on_prefix 0 foo "$(nvm_version_dir new)"
unset NPM_CONFIG_PREFIX
EXPECTED_OUTPUT='nvm is not compatible with the "NPM_CONFIG_PREFIX" environment variable: currently set to "bar"
Run `unset NPM_CONFIG_PREFIX` to unset it.'
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'NPM_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_4" ] || die "'NPM_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not exit with 4; got '$CAPTURED_EXIT_CODE'"
# on Windows, a prefix that does not exist can not be resolved, but it is still not inside `$NVM_DIR`
(
nvm_get_os() { nvm_echo win; }
NPM_CONFIG_PREFIX=bar try_err nvm_die_on_prefix 0 foo "$(nvm_version_dir new)"
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "on Windows, 'NPM_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_4" ] || die "on Windows, 'NPM_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not exit with 4; got '$CAPTURED_EXIT_CODE'"
) || die 'nvm_die_on_prefix must not skip an unresolvable NPM_CONFIG_PREFIX on Windows'
npm_CONFIG_PREFIX=bar try_err nvm_die_on_prefix 0 foo "$(nvm_version_dir new)"
unset npm_CONFIG_PREFIX
EXPECTED_OUTPUT='nvm is not compatible with the "npm_CONFIG_PREFIX" environment variable: currently set to "bar"
Run `unset npm_CONFIG_PREFIX` to unset it.'
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'npm_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_4" ] || die "'npm_CONFIG_PREFIX=bar nvm_die_on_prefix 0 foo' did not exit with 4; got '$CAPTURED_EXIT_CODE'"
OUTPUT="$(export FOO='This contains NPM_CONFIG_PREFIX' ; nvm_die_on_prefix 0 foo "$(nvm_version_dir new)" 2>&1)"
[ -z "$OUTPUT" ] || die "'nvm_die_on_prefix' was not a noop; got '$OUTPUT'"
# npmrc tests
(
cd "${TEST_DIR}"
touch package.json
# project: prefix
echo 'prefix=garbage' > .npmrc
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your project npmrc file ($(nvm_sanitize_path "${TEST_DIR}")/.npmrc)
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has prefix did not exit with 10; got '$CAPTURED_EXIT_CODE'"
# project: globalconfig
echo 'globalconfig=garbage' > .npmrc
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your project npmrc file ($(nvm_sanitize_path "${TEST_DIR}")/.npmrc)
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with project .npmrc that has globalconfig did not exit with 10; got '$CAPTURED_EXIT_CODE'"
rm "${TEST_DIR}/.npmrc" || die '.npmrc could not be removed'
mkdir -p "${TEST_VERSION_DIR}"
GLOBAL_NPMRC="${TEST_VERSION_DIR}/etc/npmrc"
mkdir -p "${TEST_VERSION_DIR}/etc"
BUILTIN_NPMRC="${TEST_VERSION_DIR}/lib/node_modules/npm/npmrc"
mkdir -p "${TEST_VERSION_DIR}/lib/node_modules/npm/"
export HOME="${TEST_VERSION_DIR}"
USER_NPMRC="${TEST_VERSION_DIR}/.npmrc"
# global: prefix
echo 'prefix=garbage' > "${GLOBAL_NPMRC}"
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your global npmrc file ($(nvm_sanitize_path "${GLOBAL_NPMRC}"))
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has prefix did not exit with 10; got '$CAPTURED_EXIT_CODE'"
# global: globalconfig
echo 'globalconfig=garbage' > "${GLOBAL_NPMRC}"
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your global npmrc file ($(nvm_sanitize_path "${GLOBAL_NPMRC}"))
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with global npmrc that has globalconfig did not exit with 10; got '$CAPTURED_EXIT_CODE'"
rm "${GLOBAL_NPMRC}" || die "${GLOBAL_NPMRC} could not be removed"
# builtin: prefix
echo 'prefix=garbage' > "${BUILTIN_NPMRC}"
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your builtin npmrc file ($(nvm_sanitize_path "${BUILTIN_NPMRC}"))
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has prefix did not exit with 10; got '$CAPTURED_EXIT_CODE'"
# builtin: globalconfig
echo 'globalconfig=garbage' > "${BUILTIN_NPMRC}"
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your builtin npmrc file ($(nvm_sanitize_path "${BUILTIN_NPMRC}"))
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with builtin npmrc that has globalconfig did not exit with 10; got '$CAPTURED_EXIT_CODE'"
rm "${BUILTIN_NPMRC}" || die "${BUILTIN_NPMRC} could not be removed"
# user: prefix
echo 'prefix=garbage' > "${USER_NPMRC}"
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your user’s .npmrc file ($(nvm_sanitize_path "${USER_NPMRC}"))
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has prefix did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has prefix did not exit with 10; got '$CAPTURED_EXIT_CODE'"
# user: globalconfig
echo 'globalconfig=garbage' > "${USER_NPMRC}"
try_err nvm_die_on_prefix 0 foo "${TEST_VERSION_DIR}"
EXPECTED_OUTPUT="Your user’s .npmrc file ($(nvm_sanitize_path "${USER_NPMRC}"))
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Run \`foo\` to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has globalconfig did not error with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_10" ] || die "'nvm_die_on_prefix 0 foo' with user .npmrc that has globalconfig did not exit with 10; got '$CAPTURED_EXIT_CODE'"
)
# "delete the prefix": npm must not load the (untrusted) project npmrc, which could otherwise choose
# the file npm rewrites via `userconfig`/`globalconfig`/`location`, and the project npmrc is never edited
(
DELETE_DIR="${TEST_DIR}/delete-prefix"
DELETE_VERSION_DIR="${DELETE_DIR}/version"
DELETE_PROJECT_DIR="${DELETE_DIR}/project"
DELETE_HOME="${DELETE_DIR}/home"
mkdir -p "${DELETE_VERSION_DIR}/etc" "${DELETE_VERSION_DIR}/lib/node_modules/npm" "${DELETE_PROJECT_DIR}" "${DELETE_HOME}"
export HOME="${DELETE_HOME}"
echo 'prefix=garbage' > "${DELETE_VERSION_DIR}/lib/node_modules/npm/npmrc"
echo 'prefix=garbage' > "${DELETE_VERSION_DIR}/etc/npmrc"
echo 'prefix=garbage' > "${DELETE_HOME}/.npmrc"
cd "${DELETE_PROJECT_DIR}" || die 'could not cd to the project dir'
touch package.json
PROJECT_NPMRC_CONTENTS="prefix=garbage
userconfig=${DELETE_HOME}/victim
location=global
globalconfig=${DELETE_HOME}/victim"
echo "${PROJECT_NPMRC_CONTENTS}" > .npmrc
NPM_CALLS="${DELETE_DIR}/npm-calls"
npm() {
echo "$*" >> "${NPM_CALLS}"
}
try_err nvm_die_on_prefix 1 foo "${DELETE_VERSION_DIR}"
EXPECTED_OUTPUT="Your project npmrc file ($(nvm_sanitize_path "${DELETE_PROJECT_DIR}")/.npmrc)
has a \`globalconfig\` and/or a \`prefix\` setting, which are incompatible with nvm.
Project npmrc files are not modified by \`--delete-prefix\`; edit that file to unset it."
[ "_$CAPTURED_STDERR" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 1 foo' with a project .npmrc that has prefix did not warn with '$EXPECTED_OUTPUT'; got '$CAPTURED_STDERR'"
[ "_$CAPTURED_EXIT_CODE" = "_0" ] || die "'nvm_die_on_prefix 1 foo' with a project .npmrc that has prefix did not exit with 0; got '$CAPTURED_EXIT_CODE'"
EXPECTED_OUTPUT="config --loglevel=warn delete prefix --userconfig=${DELETE_VERSION_DIR}/lib/node_modules/npm/npmrc --prefix=${DELETE_VERSION_DIR}
config --loglevel=warn delete globalconfig --userconfig=${DELETE_VERSION_DIR}/lib/node_modules/npm/npmrc --prefix=${DELETE_VERSION_DIR}
config --global --loglevel=warn delete prefix --prefix=${DELETE_VERSION_DIR}
config --global --loglevel=warn delete globalconfig --prefix=${DELETE_VERSION_DIR}
config --loglevel=warn delete prefix --userconfig=${DELETE_HOME}/.npmrc --prefix=${DELETE_VERSION_DIR}
config --loglevel=warn delete globalconfig --userconfig=${DELETE_HOME}/.npmrc --prefix=${DELETE_VERSION_DIR}"
OUTPUT="$(cat "${NPM_CALLS}")"
[ "_$OUTPUT" = "_$EXPECTED_OUTPUT" ] || die "'nvm_die_on_prefix 1 foo' did not run npm with a pinned \`--prefix\` (and never for the project npmrc): expected '$EXPECTED_OUTPUT'; got '$OUTPUT'"
[ "_$(cat .npmrc)" = "_${PROJECT_NPMRC_CONTENTS}" ] || die "'nvm_die_on_prefix 1 foo' edited the project .npmrc; got '$(cat .npmrc)'"
) || die "'nvm_die_on_prefix 1 foo' let a project .npmrc influence npm"
# nvm_npmrc_bad_news_bears matches `^(prefix|globalconfig) *=`
NPMRC="${TEST_DIR}/bad-news.npmrc"
printf 'prefix=x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix=x should be bad news'
printf 'prefix =x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix =x should be bad news'
printf 'prefix =x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix =x should be bad news'
printf 'prefix =\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix = should be bad news'
printf 'foo=1\nprefix = y\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a matching line after a non-matching line should be bad news'
printf 'prefix=x' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix=x without a trailing newline should be bad news'
printf 'globalconfig=x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'globalconfig=x should be bad news'
printf 'globalconfig = x\n' > "${NPMRC}"
nvm_npmrc_bad_news_bears "${NPMRC}" || die 'globalconfig = x should be bad news'
printf 'prefixfoo=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefixfoo=x should not be bad news'
printf 'globalconfigfoo=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'globalconfigfoo=x should not be bad news'
printf 'prefix x=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'prefix x=x should not be bad news'
printf 'prefix\t=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a tab before = should not be bad news'
printf ' prefix=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a leading space should not be bad news'
printf 'Prefix=x\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'an uppercase key should not be bad news'
printf 'prefix\n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'a bare prefix should not be bad news'
printf 'prefix \n' > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'trailing spaces without = should not be bad news'
: > "${NPMRC}"
! nvm_npmrc_bad_news_bears "${NPMRC}" || die 'an empty npmrc should not be bad news'
! nvm_npmrc_bad_news_bears || die 'a missing argument should not be bad news'
! nvm_npmrc_bad_news_bears "${TEST_DIR}/nonexistent.npmrc" || die 'a missing file should not be bad news'
# the npmrc scan must not fork `grep`
(
rm -f "${TEST_DIR}/grep-was-called"
nvm_grep() { : > "${TEST_DIR}/grep-was-called"; return 1; }
printf 'globalconfig = nope\n' > "${TEST_DIR}/probe.npmrc"
NVM_PROBE_EXIT=0
nvm_npmrc_bad_news_bears "${TEST_DIR}/probe.npmrc" || NVM_PROBE_EXIT=$?
[ ! -e "${TEST_DIR}/grep-was-called" ] || exit 10
[ "${NVM_PROBE_EXIT}" = 0 ] || exit 11
) || die 'nvm_npmrc_bad_news_bears must read npmrc files without calling nvm_grep'
cleanup