diff --git a/nvm.sh b/nvm.sh index 486126c6..87623223 100755 --- a/nvm.sh +++ b/nvm.sh @@ -2506,10 +2506,16 @@ nvm_download_artifact() { local VERSION VERSION="${4}" - if [ -z "${VERSION}" ]; then - nvm_err 'A version number is required.' - return 3 - fi + case "${VERSION}" in + '') + nvm_err 'A version number is required.' + return 3 + ;; + *[!0-9A-Za-z._+-]*) + nvm_err 'Invalid version: contains disallowed characters' + return 3 + ;; + esac if [ "${KIND}" = 'binary' ] && ! nvm_binary_available "${VERSION}"; then nvm_err "No precompiled binary available for ${VERSION}." diff --git a/test/fast/Unit tests/nvm_download_artifact version injection b/test/fast/Unit tests/nvm_download_artifact version injection new file mode 100755 index 00000000..b7b79329 --- /dev/null +++ b/test/fast/Unit tests/nvm_download_artifact version injection @@ -0,0 +1,46 @@ +#!/bin/sh + +WORK="${TMPDIR:-/tmp}/nvm_version_injection.$$" +PROOF="${WORK}/PWNED" + +cleanup () { + unset -f die cleanup nvm_download + rm -rf "${WORK}" +} +die () { echo "$@" ; cleanup ; exit 1; } + +\. ../../../nvm.sh + +mkdir -p "${WORK}" +export NVM_DIR="${WORK}" + +# GHSA-3c52-35h2-gfmm: a mirror-supplied version with shell/awk metacharacters +# must be rejected before it is used in URLs, paths, or awk. Neutralize network. +nvm_download () { return 0; } + +# given a version containing command-substitution syntax +# when nvm_download_artifact is asked to download it +# then it is rejected for disallowed characters and nothing is executed +rm -f "${PROOF}" +out="$(nvm_download_artifact node source std 'v1$(touch '"${PROOF}"')' 2>&1 &1