[Fix] nvm_download: pass $NVM_AUTH_HEADER to curl and GNU Wget in a config file, not as an argument
The header was passed as a `--header` argument, so it was readable by anyone who could see the downloader's command line. curl now reads it as `header = "…"` from a config on stdin (`--config -`); the sanitized value can contain neither `"` nor `\` nor a line break, so it cannot escape the quoted string or add another option. GNU Wget only reads a config file that is a regular file, so a subshell writes the header to a `mktemp` file in `$TMPDIR` (mode 0600), after a copy of the user's `$WGETRC` or `~/.wgetrc`, which that file replaces, and points `WGETRC` at it; traps on EXIT, HUP, INT, and TERM remove it, and `WGETRC` never reaches the user's shell. BusyBox wget reads no config file and has no option for one, so it still gets the header as an argument; the README recommends curl on shared machines. Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-540RL2U6.
This commit is contained in:
5 files changed
+319
-12
No files matched your search
@@ -701,6 +701,8 @@ The header is only sent with requests for URLs under a mirror, never to any othe
|
||||
|
||||
`curl` 7.58.0 and later, which nvm prefers, drops the header when the mirror redirects to another host. When only `wget` is available, nvm makes GNU Wget follow a redirect only if it stays on the same origin (scheme, host, and port), and fails on one that does not, since `wget` would send the header there too; use `curl` with a mirror that hands downloads off to another host. Other `wget`s, like BusyBox's, cannot be kept from following redirects, and send the header wherever the mirror redirects.
|
||||
|
||||
nvm gives the header to `curl` and to GNU Wget in a config file (for GNU Wget, a private temporary file that also holds a copy of your `~/.wgetrc`), not as a command-line argument, which other users of the same machine could read. Other `wget`s, like BusyBox's, read no config file, so on a machine shared with other users, install `curl` before using `$NVM_AUTH_HEADER`.
|
||||
|
||||
`$NVM_AUTH_HEADER` is the recommended way to authenticate to a mirror. Credentials embedded in the mirror URL itself (`https://user:password@host/...`) also work, and nvm prints such URLs with the credentials masked as `***@`.
|
||||
|
||||
### Platforms without official binaries
|
||||
|
||||
@@ -219,11 +219,18 @@ nvm_download() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# every local user can read a process's arguments (`ps`, /proc/<pid>/cmdline),
|
||||
# so the credential goes to the downloader in a config file, not an argument
|
||||
if [ -n "${sanitized_header}" ]; then
|
||||
if [ "${NVM_DOWNLOADER}" = 'wget' ] && nvm_wget_is_gnu; then
|
||||
nvm_wget_same_origin "${sanitized_header}" "$@"
|
||||
if [ "${NVM_DOWNLOADER}" = 'curl' ]; then
|
||||
nvm_echo "header = \"Authorization: ${sanitized_header}\"" | command curl "$@" --config -
|
||||
return $?
|
||||
fi
|
||||
if nvm_wget_is_gnu; then
|
||||
nvm_wget_with_auth_header "${sanitized_header}" "$@"
|
||||
return $?
|
||||
fi
|
||||
# other wgets, like BusyBox's, read no config file
|
||||
set -- "$@" --header "Authorization: ${sanitized_header}"
|
||||
fi
|
||||
|
||||
@@ -243,15 +250,39 @@ nvm_url_origin() {
|
||||
}
|
||||
|
||||
# args: sanitized Authorization header value, wget arguments
|
||||
# GNU Wget only reads a config file that is a regular file, so the header goes
|
||||
# in a private temporary one; it replaces ~/.wgetrc, so that is copied into it.
|
||||
nvm_wget_with_auth_header() {
|
||||
(
|
||||
NVM_WGETRC="$(command mktemp "${TMPDIR:-/tmp}/nvm-wgetrc.XXXXXX")" || {
|
||||
nvm_err 'unable to create a temporary file for $NVM_AUTH_HEADER'
|
||||
exit 1
|
||||
}
|
||||
trap 'command rm -f "${NVM_WGETRC}"' EXIT
|
||||
trap 'exit 129' HUP
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
{
|
||||
if [ -r "${WGETRC:-${HOME-}/.wgetrc}" ]; then
|
||||
command cat "${WGETRC:-${HOME-}/.wgetrc}"
|
||||
nvm_echo
|
||||
fi
|
||||
nvm_echo "header = Authorization: ${1-}"
|
||||
} > "${NVM_WGETRC}" || exit 1
|
||||
shift
|
||||
WGETRC="${NVM_WGETRC}"
|
||||
export WGETRC
|
||||
nvm_wget_same_origin "$@"
|
||||
)
|
||||
}
|
||||
|
||||
# args: wget arguments; the header comes from $WGETRC
|
||||
# `curl -L` (7.58.0 and later) does not send a custom Authorization header to a
|
||||
# redirect target on another host, but wget sends `--header` along to every
|
||||
# redirect target on another host, but wget sends its headers along to every
|
||||
# one. So GNU Wget is stopped at every redirect, which is then followed only if
|
||||
# it stays on the same origin (scheme, host, and port). Other wgets, like
|
||||
# BusyBox's, cannot be stopped from following redirects.
|
||||
nvm_wget_same_origin() {
|
||||
local NVM_WGET_HEADER
|
||||
NVM_WGET_HEADER="Authorization: ${1-}"
|
||||
shift
|
||||
local NVM_WGET_URL
|
||||
NVM_WGET_URL=''
|
||||
local NVM_WGET_ARG
|
||||
@@ -268,13 +299,13 @@ nvm_wget_same_origin() {
|
||||
local NVM_WGET_REDIRECTS
|
||||
NVM_WGET_REDIRECTS=0
|
||||
while :; do
|
||||
command wget --max-redirect=0 "$@" --header "${NVM_WGET_HEADER}"
|
||||
command wget --max-redirect=0 "$@"
|
||||
NVM_WGET_EXIT_CODE=$?
|
||||
# wget exits with 8 for an HTTP error status, including a redirect it did not follow
|
||||
if [ "${NVM_WGET_EXIT_CODE}" != 8 ] || [ -z "${NVM_WGET_URL}" ]; then
|
||||
return "${NVM_WGET_EXIT_CODE}"
|
||||
fi
|
||||
NVM_WGET_LOCATION="$(command wget --max-redirect=0 -q -S -O /dev/null "${NVM_WGET_URL}" --header "${NVM_WGET_HEADER}" 2>&1 \
|
||||
NVM_WGET_LOCATION="$(command wget --max-redirect=0 -q -S -O /dev/null "${NVM_WGET_URL}" 2>&1 \
|
||||
| command awk 'tolower($1) == "location:" { print $2; exit }' | command tr -d '\r')"
|
||||
case "${NVM_WGET_LOCATION}" in
|
||||
'') return "${NVM_WGET_EXIT_CODE}" ;;
|
||||
@@ -6654,7 +6685,7 @@ nvm() {
|
||||
nvm_node_version_has_solaris_binary nvm_iojs_version_has_solaris_binary \
|
||||
nvm_curl_libz_support nvm_command_info nvm_is_zsh nvm_stdout_is_terminal \
|
||||
nvm_npmrc_bad_news_bears nvm_sanitize_auth_header nvm_auth_header_applies_to \
|
||||
nvm_wget_is_gnu nvm_url_origin nvm_wget_same_origin \
|
||||
nvm_wget_is_gnu nvm_url_origin nvm_wget_same_origin nvm_wget_with_auth_header \
|
||||
nvm_get_colors nvm_set_colors nvm_print_color_code nvm_wrap_with_color_code \
|
||||
nvm_print_color_legend \
|
||||
nvm_echo_with_colors nvm_err_with_colors \
|
||||
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/bin/sh
|
||||
|
||||
WORK="$PWD/nvm_download-auth-argv-work.$$"
|
||||
TEST_BIN="$WORK/bin"
|
||||
ARGV_LOG="$WORK/argv.log"
|
||||
STDIN_LOG="$WORK/stdin.log"
|
||||
WGETRC_LOG="$WORK/wgetrc.log"
|
||||
WGETRC_PATH_LOG="$WORK/wgetrc-path.log"
|
||||
WGETRC_MODE_LOG="$WORK/wgetrc-mode.log"
|
||||
OLDHOME="$HOME"
|
||||
|
||||
cleanup() {
|
||||
unset -f die cleanup nvm_has_executable
|
||||
unset NVM_AUTH_HEADER WGET_VERSION
|
||||
rm -rf "$WORK"
|
||||
export PATH="$OLDPATH"
|
||||
HOME="$OLDHOME"
|
||||
export HOME
|
||||
}
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
\. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
OLDPATH="$PATH"
|
||||
|
||||
# fake curl: record every argument, and what it is given on stdin
|
||||
make_fake_curl "$TEST_BIN" 'for a in "$@"; do printf "%s\n" "$a"; done > "$ARGV_LOG"
|
||||
cat > "$STDIN_LOG"'
|
||||
VERSION_MESSAGE="curl 7.99.0 (fake)"
|
||||
|
||||
# fake GNU Wget: record every argument, and the config file $WGETRC names
|
||||
{
|
||||
echo '#!/bin/sh'
|
||||
echo 'if [ "$1" = --version ]; then echo "GNU Wget 1.21.2 built on linux-gnu."; exit 0; fi'
|
||||
echo 'for a in "$@"; do printf "%s\n" "$a"; done > "$ARGV_LOG"'
|
||||
echo 'printf "%s\n" "${WGETRC-}" > "$WGETRC_PATH_LOG"'
|
||||
echo 'cat "${WGETRC:-/dev/null}" > "$WGETRC_LOG"'
|
||||
echo 'ls -l "${WGETRC:-/dev/null}" | cut -c1-10 > "$WGETRC_MODE_LOG"'
|
||||
echo 'exit 0'
|
||||
} > "$TEST_BIN/wget"
|
||||
chmod +x "$TEST_BIN/wget"
|
||||
|
||||
export ARGV_LOG STDIN_LOG WGETRC_LOG WGETRC_PATH_LOG WGETRC_MODE_LOG
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
NVM_AUTH_HEADER='Bearer test-token'
|
||||
export NVM_AUTH_HEADER
|
||||
|
||||
# given curl
|
||||
# when nvm_download sends a credential
|
||||
nvm_download -L -s 'https://nodejs.org/dist/index.tab' -o - || die 'nvm_download (curl) returned nonzero'
|
||||
# then it is not an argument, which every local user can read in the process list
|
||||
! grep -q 'test-token' "$ARGV_LOG" || die "curl received the credential as an argument; got: $(cat "$ARGV_LOG")"
|
||||
# but a header in the config curl reads from stdin
|
||||
grep -Fxqe '--config' "$ARGV_LOG" || die "curl was not told to read a config; got: $(cat "$ARGV_LOG")"
|
||||
[ "$(cat "$STDIN_LOG")" = 'header = "Authorization: Bearer test-token"' ] || die "curl did not get the header as config; got: $(cat "$STDIN_LOG")"
|
||||
|
||||
# given a credential with a line break in it
|
||||
NVM_AUTH_HEADER="$(printf 'Bearer test-token\noutput = /tmp/nvm-pwned')"
|
||||
nvm_download -L -s 'https://nodejs.org/dist/index.tab' -o - || die 'nvm_download (curl) returned nonzero for a line break'
|
||||
# then it cannot add another option to the config
|
||||
[ "$(wc -l < "$STDIN_LOG")" -eq 1 ] || die "a line break in the credential reached curl's config; got: $(cat "$STDIN_LOG")"
|
||||
NVM_AUTH_HEADER='Bearer test-token'
|
||||
|
||||
# given only GNU Wget, and the user's own ~/.wgetrc
|
||||
nvm_has_executable() { [ "$1" != curl ] && command -v "$1" >/dev/null 2>&1; }
|
||||
HOME="$WORK/home"
|
||||
export HOME
|
||||
mkdir -p "$HOME"
|
||||
printf 'tries = 7' > "$HOME/.wgetrc"
|
||||
# when nvm_download sends a credential
|
||||
nvm_download -L -s 'https://nodejs.org/dist/index.tab' -o - || die 'nvm_download (wget) returned nonzero'
|
||||
# then it is not an argument
|
||||
! grep -q 'test-token' "$ARGV_LOG" || die "wget received the credential as an argument; got: $(cat "$ARGV_LOG")"
|
||||
# but a header in a config file only the user can read, after the user's own settings
|
||||
[ "$(cat "$WGETRC_MODE_LOG")" = '-rw-------' ] || die "the wget config file is readable by others: $(cat "$WGETRC_MODE_LOG")"
|
||||
[ "$(sed -n 1p "$WGETRC_LOG")" = 'tries = 7' ] || die "the user's ~/.wgetrc was not kept; got: $(cat "$WGETRC_LOG")"
|
||||
[ "$(sed -n '$p' "$WGETRC_LOG")" = 'header = Authorization: Bearer test-token' ] || die "wget did not get the header as config; got: $(cat "$WGETRC_LOG")"
|
||||
# which is gone once wget is done
|
||||
[ -n "$(cat "$WGETRC_PATH_LOG")" ] || die 'wget was not given a config file'
|
||||
[ ! -e "$(cat "$WGETRC_PATH_LOG")" ] || die "the wget config file was left behind: $(cat "$WGETRC_PATH_LOG")"
|
||||
# and $WGETRC is not left set in the shell
|
||||
[ -z "${WGETRC-}" ] || die "WGETRC was left set to ${WGETRC}"
|
||||
|
||||
cleanup
|
||||
@@ -61,11 +61,11 @@ chmod +x "$TEST_BIN/wget"
|
||||
export CALL_LOG
|
||||
export PATH="$TEST_BIN:$OLDPATH"
|
||||
|
||||
# the Authorization header goes along with every request
|
||||
HEADER='<--header><Authorization: Bearer test-token>'
|
||||
# the Authorization header comes from $WGETRC, never from an argument
|
||||
HEADER=''
|
||||
run() {
|
||||
: > "$CALL_LOG"
|
||||
try_err nvm_wget_same_origin 'Bearer test-token' "$@"
|
||||
try_err nvm_wget_same_origin "$@"
|
||||
}
|
||||
|
||||
# args: description, expected calls (one per argument)
|
||||
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
#!/bin/sh
|
||||
|
||||
WORK="$PWD/nvm_wget_with_auth_header-work.$$"
|
||||
OLDHOME="$HOME"
|
||||
OLDTMPDIR="${TMPDIR-}"
|
||||
|
||||
cleanup() {
|
||||
unset -f nvm_wget_same_origin
|
||||
unset WGETRC MOCK_EXIT MOCK_KILL
|
||||
rm -rf "$WORK"
|
||||
HOME="$OLDHOME"
|
||||
export HOME
|
||||
TMPDIR="$OLDTMPDIR"
|
||||
export TMPDIR
|
||||
}
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
\. ../../../nvm.sh
|
||||
|
||||
mkdir -p "$WORK/home" "$WORK/tmp" || die 'unable to create the work directory'
|
||||
HOME="$WORK/home"
|
||||
export HOME
|
||||
TMPDIR="$WORK/tmp"
|
||||
export TMPDIR
|
||||
unset WGETRC
|
||||
|
||||
# records what wget would be run with; the real one runs `command wget`
|
||||
nvm_wget_same_origin() {
|
||||
: > "$WORK/args"
|
||||
for arg in "$@"; do
|
||||
printf '%s\n' "$arg" >> "$WORK/args"
|
||||
done
|
||||
printf '%s\n' "${WGETRC-}" > "$WORK/wgetrc-path"
|
||||
if [ -n "${WGETRC-}" ] && [ -f "${WGETRC}" ]; then
|
||||
cat "${WGETRC}" > "$WORK/wgetrc"
|
||||
ls -l "${WGETRC}" | cut -c1-10 > "$WORK/wgetrc-mode"
|
||||
else
|
||||
: > "$WORK/wgetrc"
|
||||
: > "$WORK/wgetrc-mode"
|
||||
fi
|
||||
if [ -n "${MOCK_KILL-}" ]; then
|
||||
# the subshell running this function is the parent of this `sh`
|
||||
sh -c "kill -${MOCK_KILL} \$PPID"
|
||||
return 0
|
||||
fi
|
||||
return "${MOCK_EXIT:-0}"
|
||||
}
|
||||
|
||||
reset_logs() {
|
||||
rm -f "$WORK/args" "$WORK/wgetrc-path" "$WORK/wgetrc" "$WORK/wgetrc-mode"
|
||||
}
|
||||
|
||||
assert_cleaned_up() {
|
||||
[ -n "$(cat "$WORK/wgetrc-path")" ] || die "$1: expected WGETRC to be set for wget, got it empty"
|
||||
[ ! -e "$(cat "$WORK/wgetrc-path")" ] || die "$1: expected the config file to be removed, got $(cat "$WORK/wgetrc-path") left behind"
|
||||
[ -z "$(ls -A "$WORK/tmp")" ] || die "$1: expected \$TMPDIR to be empty, got: $(ls -A "$WORK/tmp")"
|
||||
}
|
||||
|
||||
# given no wgetrc of the user's
|
||||
reset_logs
|
||||
nvm_wget_with_auth_header 'Bearer test-token' -q -O - 'https://example.com/dist/index.tab'
|
||||
EXIT_CODE=$?
|
||||
[ "$EXIT_CODE" = 0 ] || die "no wgetrc: expected exit code 0, got $EXIT_CODE"
|
||||
# then the header is the only line of the config
|
||||
[ "$(cat "$WORK/wgetrc")" = 'header = Authorization: Bearer test-token' ] || die "no wgetrc: expected only the header in the config, got >$(cat "$WORK/wgetrc")<"
|
||||
# and the remaining arguments, without the header, go to nvm_wget_same_origin
|
||||
EXPECTED_ARGS='-q
|
||||
-O
|
||||
-
|
||||
https://example.com/dist/index.tab'
|
||||
[ "$(cat "$WORK/args")" = "$EXPECTED_ARGS" ] || die "no wgetrc: expected args >$EXPECTED_ARGS<, got >$(cat "$WORK/args")<"
|
||||
! grep -q 'test-token' "$WORK/args" || die "no wgetrc: expected the credential not to be an argument, got >$(cat "$WORK/args")<"
|
||||
# in a file in $TMPDIR that only the user can read
|
||||
case "$(cat "$WORK/wgetrc-path")" in
|
||||
"$WORK/tmp/nvm-wgetrc."*) ;;
|
||||
*) die "no wgetrc: expected the config file in \$TMPDIR, got $(cat "$WORK/wgetrc-path")" ;;
|
||||
esac
|
||||
[ "$(cat "$WORK/wgetrc-mode")" = '-rw-------' ] || die "no wgetrc: expected mode -rw-------, got $(cat "$WORK/wgetrc-mode")"
|
||||
assert_cleaned_up 'no wgetrc'
|
||||
# and WGETRC does not reach the caller
|
||||
[ -z "${WGETRC+set}" ] || die "no wgetrc: expected WGETRC to stay unset, got >${WGETRC}<"
|
||||
|
||||
# given wget's exit code
|
||||
reset_logs
|
||||
MOCK_EXIT=8
|
||||
nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab'
|
||||
EXIT_CODE=$?
|
||||
unset MOCK_EXIT
|
||||
# then it is returned
|
||||
[ "$EXIT_CODE" = 8 ] || die "wget failure: expected exit code 8, got $EXIT_CODE"
|
||||
assert_cleaned_up 'wget failure'
|
||||
|
||||
# given the user's ~/.wgetrc, with no trailing newline
|
||||
reset_logs
|
||||
printf 'tries = 7' > "$HOME/.wgetrc"
|
||||
nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab' || die 'with ~/.wgetrc: expected exit code 0, got nonzero'
|
||||
# then its settings are kept, and the header is on a line of its own after them
|
||||
EXPECTED_RC='tries = 7
|
||||
header = Authorization: Bearer test-token'
|
||||
[ "$(cat "$WORK/wgetrc")" = "$EXPECTED_RC" ] || die "with ~/.wgetrc: expected >$EXPECTED_RC<, got >$(cat "$WORK/wgetrc")<"
|
||||
assert_cleaned_up 'with ~/.wgetrc'
|
||||
[ "$(cat "$HOME/.wgetrc")" = 'tries = 7' ] || die "with ~/.wgetrc: expected ~/.wgetrc unchanged, got >$(cat "$HOME/.wgetrc")<"
|
||||
|
||||
# given $WGETRC naming the user's config, alongside a ~/.wgetrc
|
||||
reset_logs
|
||||
printf 'timeout = 3\n' > "$WORK/custom-wgetrc"
|
||||
WGETRC="$WORK/custom-wgetrc"
|
||||
export WGETRC
|
||||
nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab' || die 'with $WGETRC: expected exit code 0, got nonzero'
|
||||
# then $WGETRC is the one copied, not ~/.wgetrc
|
||||
EXPECTED_RC='timeout = 3
|
||||
|
||||
header = Authorization: Bearer test-token'
|
||||
[ "$(cat "$WORK/wgetrc")" = "$EXPECTED_RC" ] || die "with \$WGETRC: expected >$EXPECTED_RC<, got >$(cat "$WORK/wgetrc")<"
|
||||
assert_cleaned_up 'with $WGETRC'
|
||||
# and the caller's WGETRC is unchanged
|
||||
[ "${WGETRC-}" = "$WORK/custom-wgetrc" ] || die "with \$WGETRC: expected WGETRC to stay $WORK/custom-wgetrc, got >${WGETRC-}<"
|
||||
[ "$(cat "$WORK/custom-wgetrc")" = 'timeout = 3' ] || die "with \$WGETRC: expected it unchanged, got >$(cat "$WORK/custom-wgetrc")<"
|
||||
|
||||
# given $WGETRC naming a file that does not exist
|
||||
reset_logs
|
||||
WGETRC="$WORK/missing-wgetrc"
|
||||
nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab' || die 'with a missing $WGETRC: expected exit code 0, got nonzero'
|
||||
# then only the header is in the config; ~/.wgetrc is not used in its place
|
||||
[ "$(cat "$WORK/wgetrc")" = 'header = Authorization: Bearer test-token' ] || die "with a missing \$WGETRC: expected only the header, got >$(cat "$WORK/wgetrc")<"
|
||||
assert_cleaned_up 'with a missing $WGETRC'
|
||||
unset WGETRC
|
||||
rm -f "$HOME/.wgetrc"
|
||||
|
||||
# given a header value with shell metacharacters
|
||||
reset_logs
|
||||
nvm_wget_with_auth_header 'Bearer $HOME `id` $(id) *' 'https://example.com/dist/index.tab' || die 'metacharacters: expected exit code 0, got nonzero'
|
||||
# then it is written verbatim
|
||||
[ "$(cat "$WORK/wgetrc")" = 'header = Authorization: Bearer $HOME `id` $(id) *' ] || die "metacharacters: expected the header verbatim, got >$(cat "$WORK/wgetrc")<"
|
||||
assert_cleaned_up 'metacharacters'
|
||||
|
||||
# given that the temporary file cannot be created
|
||||
reset_logs
|
||||
TMPDIR="$WORK/nonexistent"
|
||||
ERR="$(nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab' 2>&1 >/dev/null)"
|
||||
EXIT_CODE=$?
|
||||
TMPDIR="$WORK/tmp"
|
||||
# then it fails, says why, and never runs wget
|
||||
[ "$EXIT_CODE" = 1 ] || die "no temporary file: expected exit code 1, got $EXIT_CODE"
|
||||
case "$ERR" in
|
||||
*'unable to create a temporary file for $NVM_AUTH_HEADER'*) ;;
|
||||
*) die "no temporary file: expected an error about the temporary file, got >$ERR<" ;;
|
||||
esac
|
||||
[ ! -e "$WORK/args" ] || die "no temporary file: expected wget not to run, got args >$(cat "$WORK/args")<"
|
||||
# and stops there, before trying to write the config
|
||||
[ "$(printf '%s\n' "$ERR" | tail -n 1)" = 'unable to create a temporary file for $NVM_AUTH_HEADER' ] || die "no temporary file: expected its error to be the last thing printed, got >$ERR<"
|
||||
|
||||
# given that $TMPDIR is unset or empty
|
||||
for TMPDIR_STATE in unset empty; do
|
||||
reset_logs
|
||||
if [ "$TMPDIR_STATE" = unset ]; then
|
||||
unset TMPDIR
|
||||
else
|
||||
TMPDIR=''
|
||||
fi
|
||||
nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab'
|
||||
EXIT_CODE=$?
|
||||
TMPDIR="$WORK/tmp"
|
||||
export TMPDIR
|
||||
# then the config file goes in /tmp, and is removed afterwards
|
||||
[ "$EXIT_CODE" = 0 ] || die "$TMPDIR_STATE \$TMPDIR: expected exit code 0, got $EXIT_CODE"
|
||||
case "$(cat "$WORK/wgetrc-path")" in
|
||||
/tmp/nvm-wgetrc.*) ;;
|
||||
*) die "$TMPDIR_STATE \$TMPDIR: expected the config file in /tmp, got >$(cat "$WORK/wgetrc-path")<" ;;
|
||||
esac
|
||||
[ "$(cat "$WORK/wgetrc")" = 'header = Authorization: Bearer test-token' ] || die "$TMPDIR_STATE \$TMPDIR: expected only the header in the config, got >$(cat "$WORK/wgetrc")<"
|
||||
[ ! -e "$(cat "$WORK/wgetrc-path")" ] || die "$TMPDIR_STATE \$TMPDIR: expected the config file to be removed, got $(cat "$WORK/wgetrc-path") left behind"
|
||||
done
|
||||
|
||||
# given that the download is interrupted
|
||||
for SIGNAL_CODE in HUP:129 INT:130 TERM:143; do
|
||||
reset_logs
|
||||
MOCK_KILL="${SIGNAL_CODE%%:*}"
|
||||
nvm_wget_with_auth_header 'Bearer test-token' 'https://example.com/dist/index.tab'
|
||||
EXIT_CODE=$?
|
||||
unset MOCK_KILL
|
||||
# then the config file is removed, and the signal's exit code is returned
|
||||
[ "$EXIT_CODE" = "${SIGNAL_CODE#*:}" ] || die "SIG${SIGNAL_CODE%%:*}: expected exit code ${SIGNAL_CODE#*:}, got $EXIT_CODE"
|
||||
assert_cleaned_up "SIG${SIGNAL_CODE%%:*}"
|
||||
done
|
||||
|
||||
cleanup
|
||||
Reference in new issue
Block a user