Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions nvm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
38 changes: 38 additions & 0 deletions test/fast/Unit tests/nvm_sanitize_auth_header
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 2 additions & 2 deletions test/fast/Unit tests/security_wget_injection
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading