Automated Threat Modeling

nvm CVE-2026-10796: Brief Summary of Dual Command Injection via Malicious Mirror Version Strings

CVE-2026-10796 is a CVSS 7.5 command injection vulnerability in nvm through version 0.40.4. Unsanitized version strings from a mirror's index.tab file reach two separate sinks, nvm_download() and nvm_get_checksum(), and either one can lead to arbitrary code execution.

CVE Analysis

8 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-06-04

nvm CVE-2026-10796: Brief Summary of Dual Command Injection via Malicious Mirror Version Strings
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A dual-sink command injection in nvm (Node Version Manager) lets an attacker who controls a configured mirror execute arbitrary commands on any machine that runs nvm install. All the attacker has to do is embed shell metacharacters in the version strings the mirror serves through its index.tab file. For the millions of developers and CI/CD pipelines that rely on nvm to manage Node.js installations, a routine version-management operation becomes a potential remote code execution vector whenever a non-default or non-TLS mirror is in use.

nvm is the de facto standard tool for Node.js version management on macOS and Linux. It has approximately 93,700 GitHub stars and 10,200 forks, which puts it among the most widely adopted developer tools in the JavaScript ecosystem. It is a single shell script, and it shows up in CI/CD pipelines, Docker images, and developer workstations everywhere, which makes it core infrastructure for Node.js development workflows worldwide.

Technical Information

CVE-2026-10796 is classified as CWE-78: Improper Neutralization of Special Elements used in an OS Command. It has a CVSS v3.1 base score of 7.5 (High) and the vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H. The vulnerability affects nvm through version 0.40.4.

Root Cause

When a user runs nvm install <version>, nvm fetches the configured mirror's index.tab file to list the available Node.js and io.js versions. nvm then uses the selected version string, with no sanitization, to build download URLs and to construct shell and awk commands. The core architectural flaw is the use of eval for command execution and of direct string interpolation into awk programs. Both treat untrusted mirror data as trusted code.

Dual Injection Sinks

Two separate code paths in nvm are injection sinks for the same untrusted input.

Sink 1: eval in nvm_download()

The nvm_download() function built a curl or wget command string and executed it with eval. The version string from the mirror was interpolated directly into that command string, so if a version field contained shell command substitution (for example, $(id)), the local shell would execute it before curl or wget ever ran. Double-quoting the arguments inside eval did not prevent command substitution, so the payload got past an earlier quoting hardening from commit 0ce8f5a.

Sink 2: awk interpolation in nvm_get_checksum()

The nvm_get_checksum() function interpolated the version-derived download slug (the tarball name) directly into the text of an awk program. A crafted version string such as:

v1"==$2){system("touch${IFS}/tmp/proof")}#

could break out of the awk string literal and invoke awk's system() function. That gives arbitrary command execution entirely through the awk interpreter, without the shell's eval being involved at all.

Attack Flow

Exploitation follows these steps:

  1. The attacker gets control of the content a mirror serves. They can do this by operating a malicious mirror, compromising an existing corporate or internal mirror, running a man-in-the-middle attack on a non-TLS (HTTP) mirror connection, or poisoning DNS.

  2. The attacker crafts a malicious index.tab file with version strings that contain shell metacharacters or awk escape sequences. To the user, the poisoned entry looks like a normal Node.js version.

  3. The victim runs nvm install. nvm fetches the index.tab from the configured mirror and parses the version list, and the user selects the poisoned version (or nvm resolves to it automatically).

  4. The unsanitized version string flows into either nvm_download(), where eval executes the embedded command substitution, or nvm_get_checksum(), where awk string interpolation triggers system(). Either way, the injected commands run with the full privileges of the user running nvm.

Attack Vector Summary

VectorMechanismComplexityAffected Configurations
Malicious mirror operatorMirror serves crafted index.tab with poisoned version stringsLowAny user pointing to that mirror
Mirror content supplyAttacker provides or alters content served on a non-default mirrorMediumCorporate/internal mirrors with weak access controls
MITM on non-TLS mirrorAttacker intercepts HTTP mirror connection and injects crafted index.tabMediumhttp:// mirror URLs without TLS
DNS poisoningAttacker redirects mirror hostname to attacker-controlled serverHighAny mirror using DNS-resolvable hostnames

The default mirror (https://nodejs.org over TLS) is not affected. TLS protects against MITM, and the Node.js project controls its own index.tab content.

Relationship to CVE-2026-1665

This vulnerability is directly related to CVE-2026-1665 (CVSS 5.4), which was published on January 29, 2026 and affected nvm versions 0.40.3 and below. That earlier CVE exploited the NVM_AUTH_HEADER environment variable, which was sanitized in the curl code path but not in the wget code path. It was patched in nvm v0.40.4.

The v0.40.4 patch was incomplete. It fixed the one unsanitized NVM_AUTH_HEADER variable and left the underlying eval mechanism in nvm_download() in place. CVE-2026-10796 exploits that same eval sink through a different input: version strings supplied by a remote mirror rather than a local environment variable. That makes CVE-2026-10796 more dangerous in network-facing scenarios, because the attacker does not need local access to set environment variables.

@DavidCarliez is credited with the discovery of CVE-2026-10796 for reporting the eval sink in nvm_download(). The awk injection sink in nvm_get_checksum() turned up during an internal audit prompted by that external report.

Affected Systems and Versions

Affected: nvm (Node Version Manager) versions up to and including 0.40.4.

Fixed in: nvm version 0.40.5.

Vulnerable configurations: Any nvm installation where one or more of the following conditions apply:

  • The NVM_NODEJS_ORG_MIRROR environment variable is set to a non-default mirror URL
  • The NVM_IOJS_ORG_MIRROR environment variable is set to a non-default mirror URL
  • A mirror URL uses http:// rather than https://
  • The configured mirror is operated by an untrusted party or has weak access controls

Not affected: Installations using the default mirror (https://nodejs.org over TLS) with no custom mirror environment variables set.

Note: nvm for Windows (coreybutler/nvm-windows) is a separate project and is not affected by this CVE.

Vendor Security History

nvm's security record shows a recurring pattern of command injection vulnerabilities that come from building commands with eval:

CVEDate PublishedCVSSAffected VersionsRoot CauseFix Version
CVE-2026-16652026-01-295.4 (v4.0)0.40.3 and belowUnsanitized NVM_AUTH_HEADER in wget path via eval0.40.4
CVE-2026-107962026-06-047.5 (v3.1)0.40.4 and belowUnsanitized version strings from mirror index.tab via eval and awk interpolation0.40.5

The OpenCVE database listed only one nvm CVE before CVE-2026-10796. The path from CVE-2026-1665 to CVE-2026-10796 follows a common pattern. When several untrusted data flows converge on the same sink, patching the unsanitized inputs one at a time is not enough if the evaluating execution mechanism stays in place. The v0.40.5 fix goes further. It removes eval entirely, restructures the awk data flow, and adds input validation as defense in depth.

The nvm project accepts private vulnerability reports through GitHub, by email to ljharb, and through Tidelift.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization