{"id":"CVE-2026-121751","kind":"vulnerability","aliases":["CVE-2026-121751"],"related":[],"title":"nvm: hostile mirror's LTS index runs shell commands on version resolve","description":"Node Version Manager (nvm) is a POSIX-compliant shell function for managing multiple node.js versions. In versions 0.39.6 through 0.40.8, `nvm ls-remote` (and other commands that refresh remote LTS aliases) store the version column of the mirror's `index.tab` in `$NVM_DIR/alias/lts/` without validating it, and `nvm_normalize_lts` later evaluates any suffix of an `lts/-N` value inside shell arithmetic `$((N+1))`. Under bash and zsh, arithmetic evaluation expands command substitutions in array subscripts, so a stored value such as `lts/-10*path[$(cmd)1]` runs `cmd` as the user when the alias is later resolved by purely local commands (`nvm ls`, `nvm alias`, `nvm use --lts`, `nvm which lts/`), and in every new shell when the `default` alias is `lts/*`. Exploitation requires the victim to use a hostile mirror -- via a compromised mirror or CDN, a network man-in-the-middle of an `http://` mirror, or a maliciously configured `NVM_NODEJS_ORG_MIRROR` -- and to run an affected command. The same sink is also reachable from a project `.nvmrc`, which is treated as hardening. dash is not affected. Version 0.41.0 only passes an all-digit `lts/-N` offset to arithmetic and drops `index.tab` rows whose version is not a valid version string.","summary":"nvm stores unvalidated version strings from a remote mirror's index.tab and later evaluates them in shell arithmetic, so crafted values run commands. An attacker who controls or intercepts the mirror gets commands run as the user under bash or zsh.","severity":"low","cvss":3.1,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["bash","node","nvm","other","zsh"],"not_affected_if":["dash","default-mirror-only","trusted-https-mirror","version-outside-0.39.6-0.40.8"],"how_to_check":"- Check the installed nvm version in the shell that uses it; affected versions are `0.39.6` through `0.40.8`.\n- List files in `$NVM_DIR/alias/lts/` and look for unexpected lts alias values containing `$(` or other shell syntax.\n- Check whether `NVM_NODEJS_ORG_MIRROR` is set to a non-default or untrusted mirror, and whether `http://` mirrors are in use.","fix":"- nvm: move to `0.41.0`","status":"open","published_at":"2026-11-04T22:17:55+00:00","first_seen_at":"2026-11-04T23:08:48+00:00","triaged_at":"2026-11-04T23:10:17+00:00","updated_at":"2026-11-04T23:10:17+00:00","category":"other","confidence":0.7,"triage":{"at":"2026-11-04T23:10:17Z","model":"claude-haiku-5-5","output":{"fix":"- nvm: move to `0.41.0`","reach":"network","title":"nvm: hostile mirror's LTS index runs shell commands on version resolve","impact":"high","summary":"nvm stores unvalidated version strings from a remote mirror's index.tab and later evaluates them in shell arithmetic, so crafted values run commands. An attacker who controls or intercepts the mirror gets commands run as the user under bash or zsh.","audience":"developers","category":"other","nicknames":[],"who_cares":["nvm","bash","zsh","node"],"confidence":0.7,"fix_status":"available","needs_auth":"no","worst_case":"Commands run as the user on the developer's machine.","analyst_note":"","how_to_check":"- Check the installed nvm version in the shell that uses it; affected versions are `0.39.6` through `0.40.8`.\n- List files in `$NVM_DIR/alias/lts/` and look for unexpected lts alias values containing `$(` or other shell syntax.\n- Check whether `NVM_NODEJS_ORG_MIRROR` is set to a non-default or untrusted mirror, and whether `http://` mirrors are in use.","plain_action":"","needs_analyst":false,"not_affected_if":["dash","version-outside-0.39.6-0.40.8","trusted-https-mirror","default-mirror-only"],"who_is_affected":"Developers who run nvm 0.39.6 through 0.40.8 under bash or zsh and use a remote mirror that could be compromised or intercepted, including over plain http. Projects whose .nvmrc files are untrusted also reach the same code path, which the sources treat as hardening rather than the main risk. dash is not affected, and systems on 0.41.0 or outside the affected range can skip it.","user_interaction":"yes","needs_special_setup":"yes","severity_if_unknown":"unknown"},"cost_usd":0.001186,"input_tokens":4647,"output_tokens":1442,"severity_before":"low"},"analyst_status":null,"analyst_note":null,"search":"'+1':130C '-10':150C '-121751':15A,18A '-2026':14A,17A '0.39.6':83C '0.40.8':85C '0.41.0':249C '1':153C 'affect':227C,247C 'alia':161C,172C,187C 'alias':97C 'all-digit':253C 'also':233C 'arithmet':41B,128C,135C,260C 'array':141C 'attack':48B 'bash':19B,62B,132C 'cdn':204C 'cmd':152C,155C 'column':101C 'command':9A,46B,56B,92C,138C,168C,228C 'compliant':73C 'compromis':201C 'configur':218C 'control':50B 'craft':43B 'cve':13A,16A 'dash':244C 'default':186C 'digit':255C 'dir/alias/lts':109C 'drop':262C 'evalu':37B,118C,136C 'everi':181C 'expand':137C 'exploit':190C 'function':75C 'get':55B 'harden':243C 'hostil':2A,197C 'index':6A 'index.tab':34B,106C,263C 'insid':126C 'intercept':52B 'later':36B,117C,163C 'local':167C 'ls':88C,170C 'ls-remot':87C 'lts':5A,96C,116C,123C,149C,175C,178C,189C,256C 'malici':217C 'man':208C 'man-in-the-middl':207C 'manag':67C,77C 'middl':211C 'mirror':3A,32B,54B,104C,198C,202C,214C,222C 'multipl':78C 'n':124C,129C,257C 'network':206C 'new':182C 'node':20B,65C 'node.js':79C 'nodej':220C 'normal':115C 'nvm':1A,21B,24B,68C,86C,108C,114C,169C,171C,173C,176C,219C 'nvmrc':238C 'offset':258C 'org':221C 'pass':251C 'path':151C 'posix':72C 'posix-compli':71C 'project':237C 'pure':166C 'reachabl':234C 'refresh':94C 'remot':31B,89C,95C 'requir':191C 'resolv':12A,164C 'row':264C 'run':7A,45B,57B,154C,225C 'shell':8A,40B,74C,127C,183C 'sink':231C 'store':25B,98C,145C 'string':28B,272C 'subscript':142C 'substitut':139C 'suffix':120C 'treat':241C 'unvalid':26B 'use':174C,195C 'user':60B,158C 'valid':111C,270C 'valu':44B,125C,146C 'version':11A,27B,66C,80C,82C,100C,248C,266C,271C 'via':199C 'victim':193C 'whose':265C 'without':110C 'zsh':23B,64B,134C","nicknames":[],"mitigations":[],"who_affected":"Developers who run nvm 0.39.6 through 0.40.8 under bash or zsh and use a remote mirror that could be compromised or intercepted, including over plain http. Projects whose .nvmrc files are untrusted also reach the same code path, which the sources treat as hardening rather than the main risk. dash is not affected, and systems on 0.41.0 or outside the affected range can skip it.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":[],"ptokens":[],"labels":["bash","low","node","nvm","other","zsh"],"campaign_type":null,"first_public_at":"2026-11-04T21:26:44+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"7ffcee3d-2c14-4c3e-b844-86c6a321a158","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-121751","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-121751","severity":null,"published_at":"2026-11-04T22:17:55+00:00","modified_at":"2026-11-04T22:17:55+00:00","first_seen_at":"2026-11-04T23:08:48+00:00","fetched_at":"2026-11-04T23:08:48+00:00","note":null}],"documents":[{"id":71142,"url":"https://github.com/nvm-sh/nvm/commit/aa0572b7c48b2652a9f86276bbbf3840939981af","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":71143,"url":"https://github.com/nvm-sh/nvm/security/advisories/GHSA-7prg-rw9c-82h7","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-11-04T21:26:44+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"}],"exploit_sources":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}