# nvm_tree_contains_path: How NVM Validates Directory Paths for Security

> Learn how nvm_tree_contains_path secures your environment by validating directory paths. This nvm shell utility checks if a file path is within a specified directory for enhanced safety.

- Repository: [nvm.sh/nvm](https://github.com/nvm-sh/nvm)
- Tags: internals
- Published: 2026-02-27

---

**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`](https://github.com/nvm-sh/nvm/blob/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`](https://github.com/nvm-sh/nvm/blob/main/nvm.sh) within the nvm-sh/nvm repository. The function accepts two positional arguments:

```sh
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:

```sh
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:

```sh
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:

```sh
[ "${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`](https://github.com/nvm-sh/nvm/blob/main/nvm.sh) around lines 1320-1327, `nvm_tree_contains_path` determines whether the active `node` binary on `$PATH` belongs to an NVM-managed installation:

```sh
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:

```sh
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`](https://github.com/nvm-sh/nvm/blob/main/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

```sh

# 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

```sh

# 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

```sh

# 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`](https://github.com/nvm-sh/nvm/blob/main/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

### How does nvm_tree_contains_path handle symbolic links?

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.