mirror of
https://github.com/nvm-sh/nvm.git
synced 2026-10-25 16:03:56 +08:00
`__nvm_generate_completion` passed its word list to `compgen -W`, which runs every word through shell expansion. Since that list includes alias file names and installed version directory names, pressing Tab after `nvm use`, `nvm alias`, etc, ran any command substitution in those names, expanded variables in them, and globbed `*` against the current directory. Now the list is split with globbing disabled, and each word is matched against the current word as a literal prefix, so names are offered exactly as written Discovered by Anthropic's OSS Scanner, as bug ANT-2026-QDARMGPO; the scanner correctly classified it as not a vulnerability.
116 lines
2.6 KiB
Bash
116 lines
2.6 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# bash completion for Node Version Manager (NVM)
|
|
|
|
if ! command -v nvm &> /dev/null; then
|
|
return
|
|
fi
|
|
|
|
__nvm_generate_completion() {
|
|
declare current_word
|
|
declare word
|
|
declare glob_was_off
|
|
current_word="${COMP_WORDS[COMP_CWORD]}"
|
|
# not `compgen -W`: it expands every word (including command substitution),
|
|
# and the words include alias and version directory names
|
|
COMPREPLY=()
|
|
glob_was_off=false
|
|
case $- in
|
|
*f*) glob_was_off=true ;;
|
|
esac
|
|
set -f
|
|
for word in $1; do
|
|
case "${word}" in
|
|
"${current_word}"*) COMPREPLY+=("${word}") ;;
|
|
esac
|
|
done
|
|
if [ "${glob_was_off}" = false ]; then
|
|
set +f
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
__nvm_commands() {
|
|
declare current_word
|
|
declare command
|
|
|
|
current_word="${COMP_WORDS[COMP_CWORD]}"
|
|
|
|
COMMANDS='
|
|
help install uninstall use run exec
|
|
alias unalias reinstall-packages
|
|
current list ls list-remote ls-remote
|
|
install-latest-npm
|
|
cache deactivate unload
|
|
version version-remote which'
|
|
|
|
if [ ${#COMP_WORDS[@]} == 4 ]; then
|
|
|
|
command="${COMP_WORDS[COMP_CWORD - 2]}"
|
|
case "${command}" in
|
|
alias) __nvm_installed_nodes ;;
|
|
esac
|
|
|
|
else
|
|
|
|
case "${current_word}" in
|
|
-*) __nvm_options ;;
|
|
*) __nvm_generate_completion "${COMMANDS}" ;;
|
|
esac
|
|
|
|
fi
|
|
}
|
|
|
|
__nvm_options() {
|
|
OPTIONS=''
|
|
__nvm_generate_completion "${OPTIONS}"
|
|
}
|
|
|
|
__nvm_installed_nodes() {
|
|
__nvm_generate_completion "$(nvm_ls) $(__nvm_aliases)"
|
|
}
|
|
|
|
__nvm_aliases() {
|
|
declare aliases
|
|
aliases=""
|
|
if [ -d "${NVM_DIR}/alias" ]; then
|
|
aliases="$(command cd "${NVM_DIR}/alias" && command find "${PWD}" -type f | command sed "s:${PWD}/::")"
|
|
fi
|
|
echo "${aliases} node stable unstable iojs"
|
|
}
|
|
|
|
__nvm_alias() {
|
|
__nvm_generate_completion "$(__nvm_aliases)"
|
|
}
|
|
|
|
__nvm() {
|
|
declare previous_word
|
|
previous_word="${COMP_WORDS[COMP_CWORD - 1]}"
|
|
|
|
case "${previous_word}" in
|
|
use | run | exec | ls | list | uninstall) __nvm_installed_nodes ;;
|
|
alias | unalias) __nvm_alias ;;
|
|
*) __nvm_commands ;;
|
|
esac
|
|
|
|
return 0
|
|
}
|
|
|
|
# complete is a bash builtin, but recent versions of ZSH come with a function
|
|
# called bashcompinit that will create a complete in ZSH. If the user is in
|
|
# ZSH, load and run bashcompinit before calling the complete function.
|
|
if [[ -n ${ZSH_VERSION-} ]]; then
|
|
# First calling compinit (only if not called yet!)
|
|
# and then bashcompinit as mentioned by zsh man page.
|
|
if ! command -v compinit > /dev/null; then
|
|
autoload -U +X compinit && if [[ ${ZSH_DISABLE_COMPFIX-} = true ]]; then
|
|
compinit -u
|
|
else
|
|
compinit
|
|
fi
|
|
fi
|
|
autoload -U +X bashcompinit && bashcompinit
|
|
fi
|
|
|
|
complete -o default -F __nvm nvm
|