[Fix] nvm_alias, nvm_version_path: reject .. path components

`nvm_alias` concatenated the requested name onto `$NVM_DIR/alias` and read whatever that resolved to,
so a name with a `..` component escaped the alias dir
- under the default layout, `../../.npmrc` reaches `$HOME/.npmrc`.
`nvm_print_alias_file` echoes every non-comment line of what it opens,
and `nvm use` reports the first one in its "is not yet installed" error,
so an untrusted `.nvmrc` could disclose any file the invoking user can read.

The write side already rejected `..` in an alias name (9275c5ba);
apply the same check on the read side, and to `nvm_version_path`,
which composes a version into a path with no check of its own.

Slashes stay legal, since `lts/iron` and the `lts/*` alias file depend on them.
This commit is contained in:
Jordan Harband
2026-09-21 10:01:34 +08:00
parent 60a8da7a8e
commit 072622c748
2 changed files with 82 additions and 0 deletions
+15
View File
@@ -800,6 +800,12 @@ nvm_alias_path() {
nvm_version_path() {
local VERSION
VERSION="${1-}"
case "/${VERSION}/" in
*/../*)
nvm_err "invalid version: ${VERSION}"
return 3
;;
esac
if [ -z "${VERSION}" ]; then
nvm_err 'version is required'
return 3
@@ -1498,6 +1504,15 @@ nvm_alias() {
return 2
fi
# slashes are legal (eg `lts/iron`), but a `..` component would read outside
# the alias dir; `nvm_make_alias` rejects the same shape on the write side
case "/${ALIAS}/" in
*/../*)
nvm_err "invalid alias name: ${ALIAS}"
return 3
;;
esac
local NVM_ALIAS_PATH
NVM_ALIAS_PATH="$(nvm_alias_path)/${ALIAS}"
if [ ! -f "${NVM_ALIAS_PATH}" ]; then