nvm_tree_contains_path: How NVM Validates Directory Paths for Security

The nvm_tree_contains_path function is a shell utility in nvm.sh that verifies whether a given file path resides within a specified parent directory by traversing up the filesystem hierarchy.

The nvm_tree_contains_path function serves as a critical security and validation mechanism in the Node Version Manager (NVM) codebase. Defined in the main nvm.sh script, this function ensures that executables, configuration values, and user-provided paths actually belong to the NVM-managed directory structure before NVM operates on them.

What Is nvm_tree_contains_path?

Function Location and Signature

You can find the nvm_tree_contains_path implementation in nvm.sh within the nvm-sh/nvm repository. The function accepts two positional arguments:

nvm_tree_contains_path() {
  local tree="${1-}"
  local node_path="${2-}"
  # ... validation and traversal logic

}

The function requires both the tree (parent directory) and node_path (potential child path) arguments. If either is missing, the function outputs an error via nvm_err and returns exit code 2.

How nvm_tree_contains_path Works

Argument Validation

Before traversing the filesystem, the function performs strict argument checking:

if [ "@${tree}@" = "@@" ] || [ "@${node_path}@" = "@@" ]; then
  nvm_err "both the tree and the node path are required"
  return 2
fi

This pattern ensures that empty strings trigger the error condition, preventing undefined behavior during the directory traversal phase.

Directory Tree Traversal

The core logic implements an iterative ascent up the directory hierarchy using the dirname command:

local previous_pathdir="${node_path}"
local pathdir
pathdir=$(dirname "${previous_pathdir}")

while [ "${pathdir}" != '' ] && [ "${pathdir}" != '.' ] && [ "${pathdir}" != '/' ] \
      && [ "${pathdir}" != "${tree}" ] && [ "${pathdir}" != "${previous_pathdir}" ]; do
  previous_pathdir="${pathdir}"
  pathdir=$(dirname "${previous_pathdir}")
done

The loop continues until it encounters:

  • An empty string or current directory (.)
  • The filesystem root (/)
  • The target tree directory (success condition)
  • A path that matches the previous iteration (indicating no further ascent possible)

Return Values

The function returns shell exit code 0 (true) only when the traversal lands exactly on the tree directory:

[ "${pathdir}" = "${tree}" ]

If the loop terminates for any other reason (reaching root, empty path, or stagnation), the comparison fails and the function returns a non-zero exit code, indicating the node_path is not contained within the tree.

Where NVM Uses nvm_tree_contains_path for Path Validation

Detecting Current Node Version (nvm_ls_current)

In nvm.sh around lines 1320-1327, nvm_tree_contains_path determines whether the active node binary on $PATH belongs to an NVM-managed installation:

if nvm_tree_contains_path "${NVM_DIR}" "$(which node)"; then
  # Path is inside NVM_DIR → report the Node version managed by nvm

  echo "v$(node --version)"
else
  echo "system"
fi

This check prevents NVM from incorrectly claiming ownership of system-installed Node binaries located outside the ${NVM_DIR} hierarchy.

Validating Custom Configuration Paths (nvm_is_valid_version)

Around line 2858-2860, the function validates user-provided paths via the NVM_CONFIG_VALUE environment variable:

if [ -n "${NVM_CONFIG_VALUE-}" ] && ! nvm_tree_contains_path "${NVM_DIR}" "${NVM_CONFIG_VALUE}"; then
  echo "Invalid NVM configuration – path must be inside ${NVM_DIR}"
fi

This ensures that custom configuration values point to legitimate locations within the NVM directory structure, rejecting potentially malicious or erroneous external paths.

Security Checks Across Internal Utilities

Throughout nvm.sh, nvm_tree_contains_path guards various internal operations:

  • Alias handling: Verifies that alias symlinks resolve to paths within ${NVM_DIR}
  • Version resolution: Confirms that discovered Node installations reside in expected version subdirectories
  • Path sanitization: Prevents directory traversal attacks where user input might attempt to access files outside the NVM hierarchy

These collective checks form a defensive boundary ensuring NVM operates exclusively on files it manages.

Practical Examples

Example 1: Verifying an NVM-Managed Node Binary


# Check if the current node is managed by NVM

if nvm_tree_contains_path "${NVM_DIR}" "$(command -v node)"; then
  echo "Using NVM-managed Node"
else
  echo "Using system Node"
fi

Example 2: Validating a Version Directory


# Ensure a specific version path belongs to NVM

version_path="${NVM_DIR}/versions/node/v18.16.0"
if nvm_tree_contains_path "${NVM_DIR}" "${version_path}"; then
  echo "Valid NVM version path"
fi

Example 3: Security Check in Scripts


# Reject paths outside NVM_DIR

user_input="/etc/passwd"
if ! nvm_tree_contains_path "${NVM_DIR}" "${user_input}"; then
  echo "Error: Path must be within ${NVM_DIR}"
  exit 1
fi

Summary

  • nvm_tree_contains_path is a defensive shell function in nvm.sh that validates whether a target path descends from a specified parent directory.
  • The function uses iterative dirname traversal to walk up the filesystem hierarchy, comparing each parent against the expected tree root.
  • It returns exit code 0 only when the path is confirmed to reside within the tree, and non-zero otherwise.
  • NVM relies on this function in nvm_ls_current to distinguish between NVM-managed and system Node installations, and in nvm_is_valid_version to sanitize configuration paths.
  • The function serves as a security boundary, preventing NVM from operating on files outside its managed directory structure.

Frequently Asked Questions

The function operates on the path string provided without explicitly resolving symbolic links first. If the path contains symlinks, nvm_tree_contains_path validates the literal path structure. For accurate validation within NVM's internal usage, paths are typically normalized before being passed to this function.

What happens if I call nvm_tree_contains_path with empty arguments?

The function performs strict validation at the beginning of its execution. If either the tree or node_path argument is empty, it outputs the error message "both the tree and the node path are required" via nvm_err and returns exit code 2.

Can nvm_tree_contains_path detect if a path is exactly the tree root?

Yes, the function returns success (exit code 0) when the node_path is exactly equal to the tree argument. The final comparison [ "${pathdir}" = "${tree}" ] evaluates to true when the traversal immediately matches the tree root without needing to ascend the directory hierarchy.

Why does NVM need path validation instead of just checking file existence?

Simple existence checks cannot distinguish between NVM-managed installations and system-wide Node binaries. By using nvm_tree_contains_path, NVM ensures it only operates on versions and executables within ${NVM_DIR}, preventing version reporting errors and protecting against directory traversal vulnerabilities when processing user-provided paths.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →