From e0031a3dc18278abc51b3c91f21f3a1f577bcc2c Mon Sep 17 00:00:00 2001 From: Mathew Dodgson Date: Mon, 25 May 2026 11:14:39 +1000 Subject: [PATCH 1/5] Add all valid base64 chars to sanitize function --- nvm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nvm.sh b/nvm.sh index 295703c297..15471ae672 100755 --- a/nvm.sh +++ b/nvm.sh @@ -160,7 +160,7 @@ nvm_download() { nvm_sanitize_auth_header() { # Remove potentially dangerous characters - nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -]//g' + nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -+/=]//g' } nvm_has_system_node() { From 34a9c1fb04d924456f021b39da8e2e4a456a3727 Mon Sep 17 00:00:00 2001 From: Mathew Dodgson Date: Mon, 25 May 2026 13:44:11 +1000 Subject: [PATCH 2/5] fix sanitize function and test --- nvm.sh | 6 ++++-- test/fast/Unit tests/security_wget_injection | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/nvm.sh b/nvm.sh index 15471ae672..70a0fb0921 100755 --- a/nvm.sh +++ b/nvm.sh @@ -159,8 +159,10 @@ nvm_download() { } nvm_sanitize_auth_header() { - # Remove potentially dangerous characters - nvm_echo "$1" | command sed 's/[^a-zA-Z0-9:;_. -+/=]//g' + # Remove potentially dangerous characters; allow full base64 charset (A-Za-z0-9+/=), + # base64url charset (A-Za-z0-9-_=), and safe Bearer token chars (space, colon, dot). + # Note: '-' must be at the end of the bracket expression to be treated as a literal. + nvm_echo "$1" | command sed 's/[^a-zA-Z0-9 :_.+/=-]//g' } nvm_has_system_node() { diff --git a/test/fast/Unit tests/security_wget_injection b/test/fast/Unit tests/security_wget_injection index 0d51fd8709..ea0c2a97fb 100644 --- a/test/fast/Unit tests/security_wget_injection +++ b/test/fast/Unit tests/security_wget_injection @@ -32,9 +32,9 @@ fi # Test 2: Verify that sanitized header still works for legitimate requests # The sanitized header should only contain safe characters SANITIZED=$(nvm_sanitize_auth_header "${MALICIOUS_HEADER}") -# Verify that dangerous characters were removed +# Verify that dangerous shell metacharacters were removed case "${SANITIZED}" in - *";"*|*"touch"*|*"/tmp"*) + *";"*|*'$'*|*"\`"*) die "SECURITY FAILURE: Sanitization did not remove dangerous characters properly" ;; esac From 6ca40b26913c9f0099b1693e547a7a829e27495a Mon Sep 17 00:00:00 2001 From: Mathew Dodgson Date: Mon, 25 May 2026 13:50:59 +1000 Subject: [PATCH 3/5] unit test --- test/fast/Unit tests/nvm_sanitize_auth_header | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100755 test/fast/Unit tests/nvm_sanitize_auth_header diff --git a/test/fast/Unit tests/nvm_sanitize_auth_header b/test/fast/Unit tests/nvm_sanitize_auth_header new file mode 100755 index 0000000000..e10f1b6ef4 --- /dev/null +++ b/test/fast/Unit tests/nvm_sanitize_auth_header @@ -0,0 +1,38 @@ +#!/bin/sh + +die () { echo "$@" ; exit 1; } + +\. ../../../nvm.sh + +set -ex + +# Test 1: all standard base64 characters (RFC 4648) are preserved +STANDARD_B64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" +RESULT=$(nvm_sanitize_auth_header "${STANDARD_B64}") +[ "${RESULT}" = "${STANDARD_B64}" ] || die "FAIL: standard base64 chars were stripped. Got: '${RESULT}'" + +# Test 2: all base64url characters (RFC 4648 ยง5) are preserved +B64URL="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=" +RESULT=$(nvm_sanitize_auth_header "${B64URL}") +[ "${RESULT}" = "${B64URL}" ] || die "FAIL: base64url chars were stripped. Got: '${RESULT}'" + +# Test 3: a real JWT Bearer token (base64url-encoded header.payload.signature) is preserved +JWT_TOKEN="Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +RESULT=$(nvm_sanitize_auth_header "${JWT_TOKEN}") +[ "${RESULT}" = "${JWT_TOKEN}" ] || die "FAIL: JWT Bearer token chars were stripped. Got: '${RESULT}'" + +# Test 4: Basic auth (base64-encoded user:pass) is preserved +BASIC_TOKEN="Basic dXNlcm5hbWU6cGFzc3dvcmQ=" +RESULT=$(nvm_sanitize_auth_header "${BASIC_TOKEN}") +[ "${RESULT}" = "${BASIC_TOKEN}" ] || die "FAIL: Basic auth base64 token chars were stripped. Got: '${RESULT}'" + +# Test 5: dangerous shell metacharacters are removed +DANGEROUS="Bearer token;\`evil\`-cmd \$(inject)" +RESULT=$(nvm_sanitize_auth_header "${DANGEROUS}") +case "${RESULT}" in + *";"*|*"\`"*|*'$'*|*"("*|*")"*) + die "FAIL: dangerous shell metacharacters survived sanitization. Got: '${RESULT}'" + ;; +esac + +echo "All nvm_sanitize_auth_header tests passed" From 9304c9c264bebccfd6757419fae2f80d8946a1f3 Mon Sep 17 00:00:00 2001 From: Mathew Dodgson Date: Mon, 25 May 2026 13:59:20 +1000 Subject: [PATCH 4/5] trigger test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b98d538f6e..d2a483d928 100644 --- a/README.md +++ b/README.md @@ -692,7 +692,7 @@ Run [`npx nvmrc`](https://npmjs.com/nvmrc) to validate an `.nvmrc` file. If that You can use [`nvshim`](https://github.com/iamogbz/nvshim) to shim the `node`, `npm`, and `npx` bins to automatically use the `nvm` config in the current directory. `nvshim` is **not** supported by the `nvm` maintainers. Please [report issues to the `nvshim` team](https://github.com/iamogbz/nvshim/issues/new). -If you prefer a lighter-weight solution, the recipes below have been contributed by `nvm` users. They are **not** supported by the `nvm` maintainers. We are, however, accepting pull requests for more examples. +If you prefer a lighter-weight solution, the recipes below have been contributed by `nvm` users. They are **not** supported by the `nvm` maintainers. We are, however, accepting pull requests for more examples #### Calling `nvm use` automatically in a directory with a `.nvmrc` file From 94ea428e41766be23d71d41d972a75d65d7e4f89 Mon Sep 17 00:00:00 2001 From: Mathew Dodgson Date: Mon, 25 May 2026 14:23:07 +1000 Subject: [PATCH 5/5] revert --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2a483d928..b98d538f6e 100644 --- a/README.md +++ b/README.md @@ -692,7 +692,7 @@ Run [`npx nvmrc`](https://npmjs.com/nvmrc) to validate an `.nvmrc` file. If that You can use [`nvshim`](https://github.com/iamogbz/nvshim) to shim the `node`, `npm`, and `npx` bins to automatically use the `nvm` config in the current directory. `nvshim` is **not** supported by the `nvm` maintainers. Please [report issues to the `nvshim` team](https://github.com/iamogbz/nvshim/issues/new). -If you prefer a lighter-weight solution, the recipes below have been contributed by `nvm` users. They are **not** supported by the `nvm` maintainers. We are, however, accepting pull requests for more examples +If you prefer a lighter-weight solution, the recipes below have been contributed by `nvm` users. They are **not** supported by the `nvm` maintainers. We are, however, accepting pull requests for more examples. #### Calling `nvm use` automatically in a directory with a `.nvmrc` file