1
0
mirror of https://github.com/nvm-sh/nvm.git synced 2026-10-26 16:56:21 +08:00

[Fix] nvm_is_natural_num: reject anything but digits

`[ "$1" -eq "$1" ]` accepts more than a natural number:
a leading `+`, and leading or trailing whitespace,
and in ksh it evaluates its operands as arithmetic expressions,
so words like `install` and expressions like `1+1` or `V=1` pass too.
Values with any non-digit character are now rejected before that test.

The sunos and aix branches of `nvm_get_make_jobs` count cores with `wc -l`,
which on those platforms pads the count with whitespace,
so that count is now stripped of whitespace before it is checked

Discovered by Anthropic's OSS Scanner, as bug ANT-2026-SYLQD6PZ; the scanner correctly classified it as not a vulnerability.
This commit is contained in:
Jordan Harband
2026-10-18 23:08:21 -07:00
parent 8df635740e
commit 813b5f6dcc
3 changed files with 22 additions and 2 deletions

6
nvm.sh
View File

@@ -3247,10 +3247,11 @@ nvm_get_make_jobs() {
NVM_CPU_CORES="$(sysctl -n hw.ncpu)"
;;
"_sunos")
NVM_CPU_CORES="$(psrinfo | wc -l)"
# some `wc`s pad the count with whitespace
NVM_CPU_CORES="$(psrinfo | wc -l | command tr -d '[:space:]')"
;;
"_aix")
NVM_CPU_CORES="$(pmcycles -m | wc -l)"
NVM_CPU_CORES="$(pmcycles -m | wc -l | command tr -d '[:space:]')"
;;
*)
# `_NPROCESSORS_ONLN` is how glibc, FreeBSD, macOS, and Cygwin spell it;
@@ -3690,6 +3691,7 @@ nvm_is_natural_num() {
case "$1" in
0) return 1 ;;
-*) return 3 ;; # some BSDs return false positives for double-negated args
*[!0-9]*) return 2 ;; # `-eq` also accepts signs and whitespace, and in ksh, any arithmetic expression
*)
[ "$1" -eq "$1" ] 2>/dev/null # returns 2 if it doesn't match
;;

View File

@@ -132,6 +132,18 @@ run darwin
assert_jobs 3 'darwin uses sysctl'
assert_not_nagged 'darwin uses sysctl'
# BSD-derived `wc`s right-align the count
shim wc "echo ' 4'"
shim psrinfo 'echo 0; echo 1; echo 2; echo 3'
run sunos
assert_jobs 3 'sunos with a padded wc'
assert_not_nagged 'sunos with a padded wc'
shim pmcycles 'echo 0; echo 1; echo 2; echo 3'
run aix
assert_jobs 3 'aix with a padded wc'
assert_not_nagged 'aix with a padded wc'
export PATH="${ORIG_PATH}"
# an explicit count short-circuits detection entirely

View File

@@ -12,6 +12,12 @@ die () { echo "$@" ; exit 1; }
! nvm_is_natural_num --1 || 'double negative number is not false'
! nvm_is_natural_num 1.2 || 'decimal number is not false'
! nvm_is_natural_num 0 || die 'zero is not false'
! nvm_is_natural_num +3 || die 'explicitly positive number is not false'
! nvm_is_natural_num ' 3' || die 'leading whitespace is not false'
! nvm_is_natural_num '3 ' || die 'trailing whitespace is not false'
! nvm_is_natural_num install || die 'a word is not false'
! nvm_is_natural_num V=1 || die 'an assignment is not false'
! nvm_is_natural_num 1+1 || die 'an expression is not false'
nvm_is_natural_num 1 || die '1 is not true'
nvm_is_natural_num 2 || die '2 is not true'