Introduction
A dual sink command injection in nvm (Node Version Manager) allows an attacker who controls a configured mirror to execute arbitrary commands on any machine running nvm install, simply by embedding shell metacharacters in version strings served through the mirror's index.tab file. For the millions of developers and CI/CD pipelines relying on nvm to manage Node.js installations, this vulnerability turns a routine version management operation into 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. With approximately 93,700 GitHub stars and 10,200 forks, it is one of the most widely adopted developer tools in the JavaScript ecosystem. Its single shell script architecture and ubiquitous presence in CI/CD pipelines, Docker images, and developer workstations make it a critical piece of infrastructure for Node.js development workflows globally.
Technical Information
CVE-2026-10796 is classified as CWE-78: Improper Neutralization of Special Elements used in an OS Command with a CVSS v3.1 base score of 7.5 (High) and 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 enumerate available Node.js and io.js versions. The selected version string is then used, without any sanitization, to build download URLs and construct shell and awk commands. The core architectural flaw is the use of eval for command execution and direct string interpolation into awk programs, both of which treat untrusted mirror data as trusted code.
Dual Injection Sinks
Two distinct code paths in nvm serve as injection sinks for the same untrusted input:
Sink 1: eval in nvm_download()
The nvm_download() function constructed a curl or wget command string and executed it using eval. Because the version string from the mirror was interpolated directly into this command string, a version field containing shell command substitution (for example, $(id)) would be executed by the local shell before curl or wget ever ran. Double quoting arguments inside eval did not prevent command substitution, bypassing 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 an awk program text. 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, achieving arbitrary command execution entirely through the awk interpreter without involving the shell's eval at all.
Attack Flow
The exploitation sequence proceeds through the following steps:
-
Mirror control: The attacker establishes control over mirror content. This can be achieved by operating a malicious mirror, compromising an existing corporate or internal mirror, performing a man in the middle attack on a non TLS (HTTP) mirror connection, or through DNS poisoning.
-
Payload delivery: The attacker crafts a malicious
index.tabfile containing version strings with embedded shell metacharacters or awk escape sequences. The poisoned version entry appears as a normal Node.js version to the user. -
Trigger: When a victim runs
nvm install, nvm fetches theindex.tabfrom the configured mirror and parses the version list. The user selects (or nvm automatically resolves) the poisoned version. -
Execution: The unsanitized version string flows into either
nvm_download()(whereevalexecutes the embedded command substitution) ornvm_get_checksum()(where awk string interpolation triggerssystem()execution). In both cases, the injected commands run with the full privileges of the user running nvm.
Attack Vector Summary
| Vector | Mechanism | Complexity | Affected Configurations |
|---|---|---|---|
| Malicious mirror operator | Mirror serves crafted index.tab with poisoned version strings | Low | Any user pointing to that mirror |
| Mirror content supply | Attacker provides or alters content served on a non default mirror | Medium | Corporate/internal mirrors with weak access controls |
| MITM on non TLS mirror | Attacker intercepts HTTP mirror connection and injects crafted index.tab | Medium | http:// mirror URLs without TLS |
| DNS poisoning | Attacker redirects mirror hostname to attacker controlled server | High | Any mirror using DNS resolvable hostnames |
The default mirror (https://nodejs.org over TLS) is explicitly not affected, as 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 unsanitized in the wget code path but sanitized in the curl code path. It was patched in nvm v0.40.4.
However, the v0.40.4 patch was incomplete. It addressed the specific unsanitized NVM_AUTH_HEADER variable without removing the underlying eval mechanism in nvm_download(). CVE-2026-10796 exploits the same eval sink but through a different input vector: remote mirror supplied version strings rather than a local environment variable. This makes CVE-2026-10796 more dangerous in network facing scenarios, as the attacker does not need local access to set environment variables.
The discovery of CVE-2026-10796 was credited to @DavidCarliez for reporting the eval sink in nvm_download(). The awk injection sink in nvm_get_checksum() was discovered during an internal audit prompted by the initial external report.
Affected Systems and Versions
Affected: nvm (Node Version Manager) versions through 0.40.4 (all 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_MIRRORenvironment variable is set to a non default mirror URL - The
NVM_IOJS_ORG_MIRRORenvironment variable is set to a non default mirror URL - A mirror URL uses
http://rather thanhttps:// - 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 track record reveals a recurring pattern of command injection vulnerabilities stemming from the use of eval for command construction:
| CVE | Date Published | CVSS | Affected Versions | Root Cause | Fix Version |
|---|---|---|---|---|---|
| CVE-2026-1665 | 2026-01-29 | 5.4 (v4.0) | 0.40.3 and below | Unsanitized NVM_AUTH_HEADER in wget path via eval | 0.40.4 |
| CVE-2026-10796 | 2026-06-04 | 7.5 (v3.1) | 0.40.4 and below | Unsanitized version strings from mirror index.tab via eval and awk interpolation | 0.40.5 |
The OpenCVE database listed only one nvm CVE prior to CVE-2026-10796. The progression from CVE-2026-1665 to CVE-2026-10796 illustrates a common pattern: patching individual unsanitized inputs without removing the evaluative execution mechanism is insufficient when multiple untrusted data flows converge on the same sink. The v0.40.5 fix takes a more thorough approach by eliminating eval entirely, restructuring awk data flow, and adding input validation as defense in depth.
The nvm project supports private vulnerability reporting through GitHub, email to ljharb, and through Tidelift.
References
- CVE-2026-10796 NVD Entry
- GHSA-3c52-35h2-gfmm: nvm executes commands from a malicious mirror's version strings
- Fix: nvm_download avoid eval so mirror supplied version strings cannot inject commands
- Fix: nvm_download_artifact reject version strings with disallowed characters
- Fix: nvm_get_checksum pass the tarball name to awk as data
- CVE-2026-1665 NVD Detail (related prior CVE)
- SentinelOne: CVE-2026-1665 Node Version Manager RCE
- nvm-sh/nvm Security Advisories
- nvm-sh/nvm Security Overview
- OpenCVE: nvm CVEs and Security Vulnerabilities



